Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select separate rows per column

Tags:

matlab

octave

Say

X = [1 2;
     3 4];
c = [1 2]';

I would like to find some way of doing what it seems to me like X(:,c) should do. To write it as a for loop:

for i=1:n
   res(i) = X(i, c(i));
end
% res = [1 4]

is there a single statement / vectorized way of doing this?

like image 857
Xodarap Avatar asked Dec 13 '22 01:12

Xodarap


2 Answers

diag(X(:,c)) should do the trick

Explanation: A (slightly more complicated) example will help understand.

>>X = [1 2; 3 4; 5 6; 7 8]

X =

     1     2
     3     4
     5     6
     7     8

>> c = [1 1 2 1];
>> R = X(:,c)

R =

     1     1     2     1
     3     3     4     3
     5     5     6     5
     7     7     8     7

So what's going on here? For each element in vector c, you're picking one of the columns from the original matrix X: For the first column of R, use the first column of X. For the second column of R, use the first column of X (again). For the third column of R, use the second column of X... and so on.

The effect of this is that the element you're interested in (defined in c) is located along the diagonal of the matrix R. Get just the diagonal using diag:

>>diag(R)

ans =

1
3
6
7
like image 124
tmpearce Avatar answered Dec 28 '22 01:12

tmpearce


Use sub2ind to convert to linear indices

X = [1 2;
     3 4];
c = [1 2]';

idx = sub2ind(size(X),1:numel(c),c(:)');
res = X(idx);

(I used c(:)' to get c in the correct size.)

Result:

res =

 1     4
like image 26
Gunther Struyf Avatar answered Dec 28 '22 03:12

Gunther Struyf