How to β€œsplit” a matrix in Matlab using a combination of logical indexing and slicing?

I have a matrix M that looks something like this:

M = [ 1, 2, 3, 0, 0; 1, 2, 0, 0, 0; 2, 3, 4, 5, 0; 4, 5, 6, 0, 0; 1, 2, 3, 4, 5; ] 

I am trying to get a column vector with the smallest nonzero value of each row in A, but ONLY for rows that have the first column == 1.

I can calculate filter for strings:

 r = M( :, 1 ) == 1; > r = [ 1; 1; 0; 0; 1 ] 

And I have a set of indices for the "rightmost nonzero value of each row in M":

 > c = [ 3, 2, 4, 3, 5 ] 

How to combine them in section A to get what I'm looking for? I am looking for something like:

 A( r, c ) > ans = [ 3; 2; 5 ] 

But for some reason I get a 3x3 matrix.

+4
source share
5 answers

The shortest way I can think of is this:

 % Get the values of the last non-zero entry per row v = M(sub2ind(size(M), 1:size(M,1), c)) % Filter out the rows that does not begin with 1. v(r == 1) 
+1
source

This works (I assume other operations are being done that define r,c ):

 M(sub2ind(size(A),find(r==1).',c(r==1))).' 

A brief interpretation of the problem and solution:

 M( r, c ) 

gives a 3 x 5 matrix (not 3 x 1 as desired) due to the mixing of logical and index indices. Logical indices in r highlight rows in A with r==1 . Meanwhile, the array of array c selects elements from each row in accordance with the numerical index:

 ans = 3 2 0 3 0 0 2 0 0 0 3 2 4 3 5 

What you really need is the indices of the rightmost non-zero elements in each row, starting at 1 . The solution uses linear indices (numeric) to get the correct elements from the matrix.

+1
source

I think this should do the trick. I wonder if there is a more elegant way to do this, though.

 % get only rows u want, ie with first row == 1 M2 = M(r,:); % get indices of % "the rightmost non-zero value of each row in M" % for the rows u want indicesOfinterest = c(r==1); noOfIndeciesOfinterest = numel(indicesOfinterest); % desired output column vector output = zeros(noOfIndeciesOfinterest, 1); % iterate through the indeces and select element in M2 % from each row and column indicated by the indice. for idx = 1:noOfIndeciesOfinterest output(idx) = M2(idx, indicesOfinterest(idx)); end output % it is [3; 2 ; 5] 
0
source

you can use

 arrayfun(@(x) M(x,c(x)), find(r)) 

But if you do not need r and c for other purposes, you can use

 arrayfun(@(x) M(x,find(M(x,:),1,'last')), find(M(:,1)==1)) 
0
source

Here's how to do it using linear indexing:

 N = M'; lin_index = (0:size(N,1):prod(size(N))-1) + c; v = N(lin_index); v(r) 
0
source

Source: https://habr.com/ru/post/1492823/


All Articles