How to extract elements along one dimension in an n-d array based on an arbitrary criterion.

47 vues (au cours des 30 derniers jours)
As an example, let's say that I had some 3-D array.
A = 2*rand(100,100,10) -1; % random 100x100x10 array [-1, 1]
And I want some 100x100 array extracted from A at the page determined by some arbitrary criterion. The first example would be min:
B = min(A,[],3);
which actually works; it returns a 100 x 100 array with the minimum values along A. However, what if I wanted to extract the points based off of say the absolute value, but wanted the signed versions of these:
[B, I] = min(abs(A),[],3);
does not work, as it returns the abs(A) components, not the signed version. I assume what I really want is to use the index I. However, I do not understand how to then do this efficiently, e.g. something like
B = A(I);
or
B = A(:,:,I);
Neither of these methods work; the first treats the index I across all of A, and will only pick one of the first 10 elements (incorrectly). The second simply fails because I is a 100 x 100 matrix.
There has to be an elegant way of performing this type of operation, in this example extracting the matrix that meets the chosen criterion along the page direction. It would be useful for any type of sorting or selecting where an index along one dimension is returned, e.g. max, min, find, etc.
I am hoping to do this without any kind of reshaping, but I understand that might be necessary. Something like this operation must be being performed inside of min already, and I think the answer is going to be obvious once I see it.
The above MWE is just an stand in for the kind of index selection in an N-D matrix I might want.
Thanks for your help, Dan

Réponse acceptée

Guillaume
Guillaume le 13 Déc 2016
One possible way, using ind2sub:
[~, page] = min(abs(A), [], 3);
[rows, columns] = ndgrid(size(A, 1), size(A, 2));
B = A(sub2ind(size(A), rows, columns, page));
  1 commentaire
D. Plotnick
D. Plotnick le 8 Fév 2017
Excellent idea (and exactly what I needed) with one minor correction and one addition. Your second line needs to read:
[rows, columns] = ndgrid(1:size(A, 1), 1:size(A, 2));
if
[M,N,O] = size(A)
then rows, columns, and pages need to be three matrices of size [M,N] in order for sub2ind to work.
Also, to get it into the format I wanted, also add the line
B = reshape(B, [M,N])
will return you an array with the expected size and organizational scheme.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Matrices and Arrays dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by