Rank value matrix from 3d Matrix
4 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
John Cruce
el 8 de Mayo de 2024
I have a 3d matrix of average global temperatures (0.5 degree lat/long) for 42 years (42×720×1440). For a given year (say year 42) I want to create a new matrix (720 × 1440) that ranks each lat/long pair based on the other 41 years. So if a lat/long pair is warmest, it will have a rank value of 1. If it's coolest, it will have a rank value of 42. The resulting matrix will be 720 x 1440 matrix of values ranked from 1 to 42 based on the original matrix. Is there a simple way to take a given year from the original matrix to do this without looping?
0 comentarios
Respuesta aceptada
Matt J
el 8 de Mayo de 2024
Editada: Matt J
el 8 de Mayo de 2024
Also how can NaN values be ignored in this solution?
Here's a revised method (loop-free) that also handles NaNs. As before, ranks(:,:,i) represents the rankings for year i.
T = randi(100,3,2,5); T(1)=nan; % random temp data (with NaN)
P=permute(T,[2,3,1])
nanmap=isnan(P);
P(nanmap)=-inf;
[~,ranks]=sort(P ,3,'descend');
[~,ranks]=sort(ranks,3);
ranks(nanmap)=nan
1 comentario
Matt J
el 8 de Mayo de 2024
Editada: Matt J
el 8 de Mayo de 2024
Here's a potentially more optimized implementation which requires only 1 sorting op, which is to be done with the attached file sortlidx.
T = randi(100,3,2,5); T(1)=nan; % random temp data (with NaN)
P=permute(T,[2,3,1])
nanmap=isnan(P);
P(nanmap)=-inf;
[~,I]=sortlidx(P ,3,'descend');
ranks=reshape(1:numel(I), size(P));
ranks(I)=ranks;
[~,~,ranks]=ind2sub(size(P), ranks);
ranks(nanmap)=nan
Más respuestas (1)
James Tursa
el 8 de Mayo de 2024
Editada: James Tursa
el 8 de Mayo de 2024
Might be easier to permute first so that your 2D matrices are in the first two spots. Then simply use sort() to get the rank indexing you want. E.g.,
T = randi(100,3,3,4) % random temp data
P = permute(T,[2,3,1]) % permute the data so grid is first two dimensions
[~,R] = sort(P,3,'descend') % generate the ranks based on 3rd dimension
R(:,:,1) % pick off 1st year ranks
R(:,:,2) % pick off 2nd year ranks
etc.
*** EDIT ***
Needs another step to get the rankings:
n = size(R,1) * size(R,2);
M = reshape(1:n,size(R,1),size(R,2));
K = zeros(size(R));
for k=1:size(R,3)
X = M + n * (R(:,:,k)-1);
K(X(:)) = k;
end
K
Probably a way to do this without looping but I don't see it at the moment. I just saw your NaN comment. What specifically do you want to happen with NaN values? Get lowest ranking, or ...? E.g., to force them to get lowest ranking you could just do this with the sort
[~,R] = sort(P,3,'descend','MissingPlacement','last');
5 comentarios
James Tursa
el 8 de Mayo de 2024
@John Cruce You're right, this needs another step. See my edit above.
Steven Lord
el 8 de Mayo de 2024
Can you construct a smaller 3-D array for which the solutions @Matt J and @James Tursa provided don't give the answer you expected/wanted and show the answer you did expect? As an example, give us a 3-by-4-by-5 array (something small enough to easily include in a comment) and the 4-by-5 matrix that is the right answer for that array? That concrete example may help us better understand how the provided solutions fail to satisfy your needs.
Ver también
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!