简体   繁体   中英

Find the lowest location within rows where there are non-zero elements for each column in a matrix in MATLAB

For example, I have a 4x6 matrix A:

A =

     0     0     0     0     4     3
     0     2     1     0     0     0
     0     5     0     8     7     0
     8     9    10     3     0     2

I want to find the lowest location within the rows of A where non-zero elements are found for each column. It should go like this:

column 1 => row 4
column 2 => row 2 
column 3 => row 2
column 4 => row 3
column 5 => row 1
column 6 => row 1  

And the result should look like the following vector:

Result = [4, 2, 2, 3, 1, 1] 

Anyone has any idea how to obtain this?

One approach to solve for a generic case -

[valid,idx] = max(A~=0,[],1)
out = idx.*valid

Sample run -

A =
     0     0     0     0    -4     3
     0     2     1     0     0     0
     0     5     0     8     7     0
     0     9    10     3     1     2
out =
     0     2     2     3     1     1
  • As seen from the sample run, for a case when there are all zeros (column-1), we get output of zero to indicate that there are no non-zeros in that column.

  • It also takes care of negative numbers (column-5).

This should do it:

A = [0, 0, 0, 0, 4, 3;
     0, 2, 1, 0, 0, 0;
     0, 5, 0, 8, 7, 0;
     8, 9, 10, 3, 0, 2];

indices = repmat((1:size(A))', [1, size(A, 2)]);
indices(A == 0) = NaN;
min(indices, [], 1)

Here indices is:

indices =

1   1   1   1   1   1
2   2   2   2   2   2
3   3   3   3   3   3
4   4   4   4   4   4

We then set every element of indices to NaN wherever A is zero, which gives us:

indices = 

NaN   NaN   NaN   NaN     1     1
NaN     2     2   NaN   NaN   NaN
NaN     3   NaN     3     3   NaN
  4     4     4     4   NaN     4

We then simply take the minimum of each column

I can think of one combination that uses ind2sub and unique with find , I'm sure there's a better way.

With your given A , assuming it's an array of integers:

[r, c] = ind2sub(size(A), find(A ~= 0));
[~, ia, ~] = unique(c);
result = r(ia)';

Returns:

result =

     4     2     2     3     1     1

I did it this way because find returns the linear indices of the array it's searching. MATLAB arrays are stored column-major in memory, so it's as if each column is stacked on top of the other. ind2sub converts these linear indices back to their subscripts based on the size of the original array. Then I use unique to find the first instance of each column and return those row numbers only.

一种可能的解决方案,使用sumcumsum

Result = sum(cumsum(A ~= 0) == 0) + 1;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM