Star
Star

Reputation: 2299

Finding the indices of first negative elements in a 3-d matrix in Matlab

Consider the matrix A in Matlab of dimension fxmxm, e.g. with f=4 and m=3

A(:,:,1)=[1 2 3; 4 5 6; 7 8 9; 10 11 12]

A(:,:,2)=[0.5 2 -1; 3 -1 0; 7 -5 8; 10 11 12]

A(:,:,3)=[-2 2 -2; 2 -2 -1; 7 -5 -3; 10 -2 0]

The characteristic of A is the following: consider the vector 1xm [A(i,j,1) A(i,j,2) ... A(i,j,m)]. We have that A(i,j,1)>=A(i,j,2)>=...>=A(i,j,m). This holds for any i,j with i=1,...,f and j=1,...,m.

Without using loops, I want to construct the matrix B of dimension fxm such that B(i,j) gives the index of the first negative element in [A(i,j,1) A(i,j,2) ... A(i,j,m)]. If there are no negative elements in [A(i,j,1) A(i,j,2) ... A(i,j,m)], B(i,j) should be equal to m+1.

In the example above

B=[3 4 2; 4 2 3; 4 2 3; 4 3 4]

Upvotes: 1

Views: 109

Answers (2)

Luis Mendo
Luis Mendo

Reputation: 112769

You can use the two-output form of max to act as “find along a given dimension”, as follows:

[v, B] = max(A<0, [], 3);
B(~v) = size(A,3)+1;

Upvotes: 1

rayryeng
rayryeng

Reputation: 104565

You can approach this using a combination of find, ind2sub and accumarray.

We can determine the row, column and slice locations for each of the values that are negative with find and ind2sub, take the row and column locations which will act as groups and will serve as our input key into accumarray and use the slice locations that are negative as the value associated with each key. For each of the unique row and column locations, we determine the slice number that was negative that is the smallest. The result will be a matrix where each location will tell you the first slice that was negative.

However, for those 3D columns that aren't negative, what accumarray will do is set these locations to 0. With the resulting matrix, any values that are 0, set them to m+1:

ind = find(A < 0);
[rows, cols, slices] = ind2sub(size(A), ind);
B = accumarray([rows cols], slices, [size(A,1), size(A,2)], @min);
B(B == 0) = size(A,3) + 1;

For your example, we get:

B =

     3     4     2
     4     2     3
     4     2     3
     4     3     4

Upvotes: 2

Related Questions