views:

250

answers:

1

This seems to be a very common problem of mine:

data = [1 2 3; 4 5 6];
mask = [true false true];

mask = repmat(mask, 2, 1);

data(mask) ==> [1; 4; 3; 6]

What I wanted was [1 3; 4 6].

Yes I can just reshape it to the right size, but that seems the wrong way to do it. Is there a better way? Why doesn't data(mask) return a matrix when it is actually rectangular? I understand in the general case it may not be, but in my case since my original mask is an array it always will be.

Corollary

Thanks for the answer, I just also wanted to point out this also works with anything that returns a numeric index like ismember, sort, or unique.

I used to take the second return value from sort and apply it to every column manually when you can use this notion to do it one shot.

+9  A: 

This will give you what you want:

>> data = [1 2 3; 4 5 6];
>> mask = [true false true];
>> data(:,mask)

ans =

     1     3
     4     6

This works because you can simply apply the logical index mask to the columns, selecting all the rows with :.

Even when a 2-D logical array is used for an input, the output will be a column array of indexed values. This is because there is no guarantee that the indexed elements can be organized into a 2-D (i.e. rectangular) output. Consider if your 2-D mask were the following:

mask = [true false true; true false false];

This would index 3 values, which can't be organized into anything but a row or column vector for the output. Here's another example:

mask = [true true true; true false false];

This would index 4 values, but 3 are from the first row and 1 is from the second row. How should these values be shaped into a rectangular output matrix? Since there's no clear way to do this in general for an arbitrary 2-D index matrix, a column vector of indexed values is returned.

gnovice
Thanks, I knew it was something simple like that. Never considered using the : notion with an mask. I've only used a single index.
Pyrolistical