Find column number for every row in matrix
19 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Chun Chi Wyman Chung
el 15 de Mzo. de 2023
Editada: John D'Errico
el 15 de Mzo. de 2023
Hello,
I'm trying to extract the column number of the first positive value in a matrix for every row, without using any loops.
For instance
-1 4 1
1 -1 -1
-5 4 -1
I want the output column vector to be:
2
1
2
I've attempted using find(), but I cannot restrict it to when there are multiple positive values in the same row.
0 comentarios
Respuesta aceptada
Stephen23
el 15 de Mzo. de 2023
Editada: Stephen23
el 15 de Mzo. de 2023
M = [-1,4,1;1,-1,-1;-5,4,-1]
Method one: logical array, CUMSUM, and FIND:
X = M>=0;
Y = X&cumsum(X,2)==1;
[C,~] = find(Y.')
Method two: NUM2CELL, ARRAYFUN, and FIND:
C = cellfun(@(v)find(v>=0,1,'first'),num2cell(M,2))
Method three: CUMPROD and SUM:
C = 1+sum(cumprod(M<0,2),2)
Method four: CUMPROD, ONES, and MTIMES:
C = 1+cumprod(M<0,2)*ones(size(M,2),1)
Method five: CUMSUM and MAX:
[~,C] = max(cumsum(M>=0,2)==1,[],2)
Method six: CUMMAX, SIGN, MIN, and SUM:
C = 1-sum(min(0,sign(cummax(M,2))),2)
Method seven: FIND and ACCUMARRAY:
[R,C] = find(M>=0);
C = accumarray(R,C,[],@min)
Method eight: is left as an exercise for the reader.
0 comentarios
Más respuestas (4)
the cyclist
el 15 de Mzo. de 2023
Here is one way:
M = [-1 4 1;
1 -1 -1;
-5 4 -1];
[r,c] = find(M>0);
[~,j] = unique(r);
out = c(j)
0 comentarios
David Hill
el 15 de Mzo. de 2023
a=[ -1 4 1
1 -1 -1
-5 4 -1];
A=(a>0)';
[b,d]=find(A);
[~,e]=unique(d);
b(e)
0 comentarios
Les Beckham
el 15 de Mzo. de 2023
Editada: Les Beckham
el 15 de Mzo. de 2023
A = [ -1 4 1
1 -1 -1
-5 4 -1 ];
[row, col] = find(A > 0)
[~,idx,~] = unique(row, 'first')
col(idx)
0 comentarios
John D'Errico
el 15 de Mzo. de 2023
Editada: John D'Errico
el 15 de Mzo. de 2023
Simple. One line.
A = randi([-5,5],[10,7])
[~,col] = max(A > 0,[],2)
Why does it work? A > 0 returns an array that is true (1) only when a number is positive.
Max returns the location of the first such element (among equal maxes) that it finds. And since the A>0 matrix is a boolean one, it is composed of only 0 and 1 elements.
Will this fail if there are no positive elements at all in a row? Well, yes. In that case, it will return 1 for those rows.
But that is true of almost any of the schemes suggested by others. If you want a scheme that will return perhaps a NaN for those rows where there were no positive elements, you could patch it by one more test. I'll regenerate a new matrix with only a few columns, but many negative elements, to insure at least one row will have all non-positive elements.
A = randi([-10,5],[10,3])
[~,col] = max(A > 0,[],2);
col(~any(A>0,2)) = NaN
As you can see, in this final result, rows {2,7,8} had no positive elements at all, so a NaN was generated for those rows.
Or, perhaps you don't want to see a NaN generated. What we might do here is to append an extra column, that is ALWAYS positive. This is a common trick one can employ.
[~,col] = max([A,ones(size(A,1),1)] > 0,[],2)
So for a 3 column array, it returns the number 4 where there were NO positive elements.
In the end, it is important that you decide what to do when NO elements are positive in a row, as you should expect to see a bug in your code at some point.
1 comentario
Les Beckham
el 15 de Mzo. de 2023
Editada: Les Beckham
el 15 de Mzo. de 2023
Except that it doesn't quite work. Row 3 has no positive elements, but this approach returns a 1 for that row.
Ver también
Categorías
Más información sobre Logical en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!