help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: multi-dimensional logical index assignment?


From: Markus Mützel
Subject: Re: multi-dimensional logical index assignment?
Date: Mon, 4 May 2020 16:10:22 +0200

Am 02. Mai 2020 um 21:43 Uhr schrieb "Markus Mützel":
> Am 02. Mai 2020 um 19:36 Uhr schrieb "Nicholas Jankowski":
> > I'm trying to do a 3+ dimensional version of what is shown here:
> > https://stackoverflow.com/questions/18129298/how-to-use-double-indexing-to-redefine-matrix-values
> >  
> >  
> > and the syntax eludes me. The example shown is clear enough for a 2D 
> > matrix, e.g.,:
> >  
> > >> A = [1 2; 3 4];
> > >> A(2,:)((A(2,:)>3)) = 0
> > error: () must be followed by . or close the index chain
> > >> A(2,A(2,:)>3) = 0
> > A =
> >    1   2
> >    3   0
>
> > but if I have a 3D array and I want to change the values of 'page' 2 based 
> > on the values of 'page' 4, can that be done in a similar one line 
> > assignment without using an intermediate variable?  e.g., 
>
> > >> a = rand(2,3,4);
> > >> a(:,:,4)>0.5
> > ans =
> >   1  1  1
> >   1  1  0
> > >> a(:,:,2)(a(:,:,4)>0.5) = 0
> > error: () must be followed by . or close the index chain
> > >> a((a(:,:,4)<0.5),2) = 0
> > error: Invalid resizing operation or ambiguous assignment to an 
> > out-of-bounds array element
> >  
> > I feel like I'm missing something obvious. 
> 
> I think the problem here is that it is not possible to combine logical 
> indexing with subscript indexing.
>
> Maybe converting both to linear indices could do the trick:
> 
> a = rand (2, 3, 4);
> sz_a = size (a);
> 
> src_pg = 4;
> target_pg = 2;
> a(find (a(:,:,src_pg)<0.5) + (target_pg-1)*prod (sz_a(1:2))) = 0;
> 
> 
> "find" effectively converts the logical indices to linear indices. The rest 
> is an offset to index into the second page.

I couldn't stop thinking about this problem because I don't like to use "find" 
if it can be avoided.
Turns out that it *is* possible to combine logical and subscript indexing (and 
this is something I use quite often).
The problem is however, that Octave (and Matlab) don't understand that you want 
to apply the logical index to several dimensions.
So what it effectively does is:
a = rand (2,3,4);
idx = a(:,:,4) < 4;
a(idx(:),:) = 0;  # This indexing fails because idx has more elements than 
size(a,1)

The following few lines are probably much more efficient than the approach with 
"find" if you do the reshape assignments in-place:
a = rand (2,3,4);
sz_a = size (a);
a = reshape (a, prod (sz_a(1:2)), sz_a(3));
a(a(:,4)<0.5,2) = 0;
a = reshape (a, sz_a);

HTH,
Markus




reply via email to

[Prev in Thread] Current Thread [Next in Thread]