Average based on logical mask and condition

I want to average the data according to unique ID and a logical mask. I have 3 km logical mask which will average into perfect 36 km grid. I average into 36 km based on compartmentID I created. I'm having trouble, when I want to discard those 36 km grids when one of the 3 km grid is zero (based on logical mask ID). Size of the matrix is 406, 964 for 36 km grid which perfectly fit 4872, 11568 3 km grids.
%Form the ID's for 3 km grid so to average for 36 km grid.
rowId = ceil( (1 : 4872) / 12 );
colId = ceil( (1 : 11568) / 12 );
[colID, rowID] = meshgrid( colId, rowId );
compartmentID = colID + (rowID - 1) * max(colId);
Average = reshape(accumarray(compartmentID(:),reshape(Grid_3km,[],1), [],@mean,NaN ), 406, 964);
Can anyone help me with the condition, that says if one of the 3 km grid in 36 km is zero then discard the average.

6 个评论

Any diagram, image, or screenshot to help us visualize this?
Please find the mat file attached. I need to remove all the compartment ID numbers of 36 km grid even if one of the 3 km grid within 36 km is zero. This is my code. Since there are 144 perfect 3 km grid in a 36 km grid, I wrote this code, it works but very slowly. more than 10 hrs and hasn't finished even one matrix. Unable to attach the file. It is a 4872 by 11568 matrix, it is 12 Mb after zip too. Any idea how I can attach the file? I attached picture of 1) perfect 36 km grid, where repeated numbers represent 3 km grids, 2) imperfect 36 km grid, where zero's indicate missing 3 km grid. I want to remove all the 36 km grids where even one of the 3 km is zero.
Any help is highly appreciated !!!!
x = unique(New_IMERG(1).compartment);
parfor ii=1:size(New_IMERG,1)
for jj=1:size(x,1)
A = sum(New_IMERG(ii).compartment == x(jj),1);
f sum(A) < 144
New_IMERG(ii).compartmentNEW(New_IMERG(ii).compartment==x(jj)) = 0;
end
end
end
you could try make a smaller and more general example... one where you can verify the solution quickly... e.g.
% given a large grid:
a = floor(magic(9)/20);
% find the avg of all possible 3x3 grids which don't contain zeros
one (probably slow) solution to this is:
for i = 1:size(a,1)
for j = 1:size(a,2)
if i+2<=size(a,1) & j+2<=size(a,2)
submat = a(i:i+2,j:j+2);
if any(submat(:)==0)
out(i,j) = nan;
else
out(i,j) = mean(submat(:));
end
end
end
end
disp(out)
but the problem is now easy for others to understand... and all you are looking for now is a faster solution :)
"Please find the mat file attached."
Anyone can see it? I don't.
Sorry, I could not attach it. It was larger than 5 Mb.
@JohnGalt Can you please elaborate ?

请先登录,再进行评论。

 采纳的回答

Just put NaN on the 3km-grid at the place you want to discard
Grid_3km_Masked = Grid_3km;
Grid_3km_Masked(YourMask==0) = NaN;
then by using your working code on Grid_3km_Masked, it will propagate to the average on coarse-grid data result:
%Form the ID's for 3 km grid so to average for 36 km grid.
rowId = ceil( (1 : 4872) / 12 );
colId = ceil( (1 : 11568) / 12 );
[colID, rowID] = meshgrid( colId, rowId );
compartmentID = colID + (rowID - 1) * max(colId);
Average = reshape(accumarray(compartmentID(:),reshape(Grid_3km_Masked,[],1), [],@mean,NaN ), 406, 964);

10 个评论

This is not working. The average is not right.
What you mean by "not right" what do you expect? I just interpret what you ask
"I want to discard those 36 km grids when one of the 3 km grid is zero"
meaning I think you want to completely discard the coarse result when there is one or more of the fine grid data that is/are masked. but might be I don't understood correctly.
You understood it right. When averaging it to coarse resolution the values don't add up right from non-zero 3 km grid to 36 km grid.
What you said are actually different to me (so both cannot be right):
  • "I want to discard those 36 km grids" and
  • "don't add up right from non-zero 3 km"
Doesn't mean the same to me. The first one I discard the result the second one I don't count the subpixel fine-gris in the result.
Which one is correct???
For the interpretation of "don't add up"
Grid_3km_Masked = Grid_3km .* (YourMask==1);
rowId = ceil( (1 : 4872) / 12 );
colId = ceil( (1 : 11568) / 12 );
[colID, rowID] = meshgrid( colId, rowId );
compartmentID = colID + (rowID - 1) * max(colId);
Average = accumarray(compartmentID(:),Grid_3km_Masked(:)) ./ ...
accumarray(compartmentID(:),YourMask(:)==1);
Average = reshape(Average,406, 964);
What you said are actually different to me (so both cannot be right):
"I want to discard those 36 km grids" : * YES THIS IS WHAT I WANT to discard those imperfect 36 km grids even if one of the 3 km grid is NaN.
"don't add up right from non-zero 3 km" : Assuming that those imperfect 36 km grids are discarded, the average of remaining 3 km grids (which are within the perfect 36 km) do not average correctly.
Sorry I give up, the more we discuss the more I don't understand what you want.
Sorry, I wasn't clear for you. I figured it out. Slow but works. Thanks everyone !
Do you mind to post the final working version of the code? I'm curious to see what you want to compute.
I got with the code you suggested, I just needed to transpose the matrix. Mask thing did the trick. Thanks.

请先登录,再进行评论。

更多回答(0 个)

类别

帮助中心File Exchange 中查找有关 Creating and Concatenating Matrices 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by