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.
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.