Can anyone help me with the a tentative guide on how to average across the two dimensions of a 3d array, and loop it across 86 timesteps?

 Respuesta aceptada

If you have a temperature data cube T whose dimensions correspond to lat x lon x time, the simplest way to get an 86x1 array of mean temperature time series is
Tm = squeeze(mean(mean(T,'omitnan'),'omitnan'));
then you can make a line plot of mean temperature as a function of time, like this:
plot(t,Tm)
However, I should point out that all of the grid cells in a geographic grid have areas that depend on latitude, so it's not appropriate to give equal weight to a polar and equatorial grid cells (they're very different sizes!). In the Climate Data Toolbox for Matlab, see Example 3 of wmean for what I'm talking about.
It would be much better to get the area of each grid cell in your global grid using cdtarea like this:
A = cdtarea(Lat,Lon);
Then calculate the weighted mean like this:
Tm = NaN(86,1); % (preallocate for efficiency)
% Loop through each time step:
for k = 1:86
Tm(k) = wmean(T(:,:,k),A,'all');
end
Alternatively, you could skip the loop and use the local function like this:
% Get a mask of the grid cells that always have valid data:
mask = all(isfinite(T),3);
% Calculate weighted mean temperature time series in the finite grid cells:
Tm = local(T,mask,'weight',A);

Más respuestas (1)

Let's do this with a smaller array, as the specific numbers don't seem particularly important. I'll do 5x4x3 so we can see the values easily. It's actually very easy because MATLAB works naturally with matrices of any shape, you can do this all with the mean function, no loops required:
X = rand(5,4,3)
X =
X(:,:,1) = 0.8932 0.0985 0.1182 0.5943 0.9755 0.9365 0.2791 0.4799 0.2896 0.9367 0.1734 0.3763 0.4609 0.2365 0.5636 0.9141 0.5024 0.1773 0.6540 0.3962 X(:,:,2) = 0.7910 0.0458 0.9640 0.3480 0.2623 0.8134 0.1968 0.5781 0.9564 0.0540 0.6005 0.1332 0.0680 0.9841 0.9569 0.4038 0.8187 0.9467 0.5550 0.4149 X(:,:,3) = 0.0716 0.7523 0.6300 0.1288 0.4460 0.9575 0.0197 0.8113 0.7260 0.7879 0.5096 0.4921 0.9718 0.0751 0.3600 0.1038 0.0820 0.9162 0.4284 0.8737
a=mean(X,1) % mean across rows (same as mean(X))
a =
a(:,:,1) = 0.6243 0.4771 0.3577 0.5522 a(:,:,2) = 0.5793 0.5688 0.6546 0.3756 a(:,:,3) = 0.4595 0.6978 0.3895 0.4819
b=mean(X,2) % mean across columns
b =
b(:,:,1) = 0.4261 0.6678 0.4440 0.5438 0.4325 b(:,:,2) = 0.5372 0.4627 0.4360 0.6032 0.6838 b(:,:,3) = 0.3957 0.5586 0.6289 0.3777 0.5751
You might find the shape of these outputs to be annoying, the squeeze function is good for fixing that up:
squeeze(a)
ans = 4×3
0.6243 0.5793 0.4595 0.4771 0.5688 0.6978 0.3577 0.6546 0.3895 0.5522 0.3756 0.4819
squeeze(b)
ans = 5×3
0.4261 0.5372 0.3957 0.6678 0.4627 0.5586 0.4440 0.4360 0.6289 0.5438 0.6032 0.3777 0.4325 0.6838 0.5751

12 comentarios

Thank you so much for you reply. However, this doesnt seem to work in my case. Mayb i did not explain my question correctly. Allow me to further elucidate.
I have a climate data of type 720x360x86, where the first two dimension correpond to the latitude and longitude and third is the year. Therefore the first two dimension store climate data that correspond to the intersection of a lat and long. The third dimension is the year which can be visualised as one stacked over another. Therefore what i have are the temperature values of the intersection of lat and long for 86 years. What i want to acheive is one single mean temperature value for each year so that at the end I have 86 temperature values that i can plot against time to get a line graph.
This makes more sense, sorry about the confusion.
In recent versions of MATLAB you can use the vecdim argument to mean which allows you to specify multiple dimensions across which to take the mean (the same strategy with squeeze applies as above):
a=rand(5,4,3)
a =
a(:,:,1) = 0.4787 0.2408 0.9097 0.2210 0.2723 0.0255 0.1927 0.5562 0.4048 0.0268 0.9237 0.0372 0.3985 0.4864 0.9632 0.4663 0.5334 0.1480 0.3889 0.0175 a(:,:,2) = 0.9937 0.4855 0.0319 0.4921 0.3524 0.0650 0.2033 0.7786 0.4627 0.1363 0.2829 0.9652 0.2975 0.2428 0.0338 0.5705 0.7100 0.3389 0.2681 0.6379 a(:,:,3) = 0.2345 0.5420 0.1408 0.6675 0.0071 0.5679 0.4373 0.7349 0.9596 0.6340 0.7134 0.7136 0.4259 0.3887 0.2566 0.8295 0.5671 0.1575 0.5866 0.4548
b = mean(a,[1 2])
b =
b(:,:,1) = 0.3846 b(:,:,2) = 0.4174 b(:,:,3) = 0.5010
c = squeeze(b)
c = 3×1
0.3846 0.4174 0.5010
I'm not sure what release vecdim was introduced, if you're on a release where specifying a vector of dimensions for the mean is not supported, you can use reshape to acieve the same effect:
d = reshape(a,5*4,3) % in your case reshape(themat,720*360,86) or generally reshape(themat,height(themat)*width(themat),size(themat,3))
d = 20×3
0.4787 0.9937 0.2345 0.2723 0.3524 0.0071 0.4048 0.4627 0.9596 0.3985 0.2975 0.4259 0.5334 0.7100 0.5671 0.2408 0.4855 0.5420 0.0255 0.0650 0.5679 0.0268 0.1363 0.6340 0.4864 0.2428 0.3887 0.1480 0.3389 0.1575
e = mean(d)
e = 1×3
0.3846 0.4174 0.5010
Thank you very much for this reply.
@Rohit shaw - Does this solve the issue? I should have said the short version is:
squeeze(mean(yourdata,[1 2]))
@Dave B unfortunately, vecdim only works with positive integers only. Also the alternative way of using reshape isnt rendering the correct ouput. If you have any other ideas, kindly let me know. Till then i will keep trying
vecdim should be taking positive integers, namely 1 and 2, as those are the dimensions across which you're taking a mean...right?
Can you clarify what you mean by isn't working correctly? I maye still be misunderstanding your problem. I read it as: take the mean for each 'slice' in 3-D matrix...
a = cat(3,[1 2;3 4],[5 6; 7 8])
a =
a(:,:,1) = 1 2 3 4 a(:,:,2) = 5 6 7 8
mean_1 = squeeze(mean(a,[1 2]))'
mean_1 = 1×2
2.5000 6.5000
mean_2 = mean(reshape(a,4,2))
mean_2 = 1×2
2.5000 6.5000
mean_3 = [mean([1 2 3 4]) mean([5 6 7 8])]
mean_3 = 1×2
2.5000 6.5000
@Dave B thank you for your reply. Yes, vecdim only takes positive integers where in my 1st and 2nd dimesion, what i have are temperature values which can be negative for certain areas on earth.
Also sorry for the ambiguos reply. What i meant was that, if the temperature values are average properly across 86 years and plotted across 86 years, I should get a clear increasing trend(as I am plotting future temperature values across time), whereas what I am getting is the image below which according my knowledge is a mean temperature of a certain point on the earth's surface which is why their are recurrent crests and troughs.
@Rohit shaw vecdim should literally be the numbers 1 and 2, they are both positive and integer. They have to be positive integers because you index into matrices with positive integers in MATLAB.
If the plot is not expected, is it possible that the data in the matrix are not what you think they are? You could check mean2(thematrix(:,:,1)) or mean2(thematrix(:,:,2)) and compare that to the first or second item in your result.
I'm pretty confident that this method works, both because I've used it often, and because of the example code above which is unambiguously correct.
@Dave B thank you for your reply Dave. While running vecdim, this is the error I am encountering when i run the vecdim function
temp2=squeeze(mean(temp,[1 2]));
Error using sum
Dimension argument must be a positive integer scalar within indexing range.
Error in mean (line 116)
y = sum(x, dim, flag) ./ size(x,dim);
Regarding the data, when I do individual means, i get the same result. Regarding the data, I am sure its correct because i have visualised the file in panoply where its fine. Also i ran the reshape function since it served the same function. I am saving the output as of now and would delibrate with my supervisor tomorrow. After using multiple functions, I m getting the same output. I can only know it tomorrow and I will surely let you know about it. Thank you for constant replies to my queries. You are very kind.
Hi Rohit - sorry again about the confusion.
The reason you're getting that error is because you're on an older version of MATLAB and vecdim isn't an available option yet. (As I mentioned above I'm not sure what release vecdim was introduced), the bit that's going wrong is not the positive/integer part but the fact that it's not scalar, as before vecdim was an option this argument was always a scalar. You can see why we added this option, it's a common question and the reshape approach is confusing!
Hope you can get to the bottom of it and I look forward to finding out what was going on.
Yes @Dave B, thank you for the reply. I have saved the output rendered by reshape and would definitely drop the comment here about how it goes. It's just that I am quite new to such things hence the constant barge of queries. Anyways, thanks for ur constant replies. Have a goood evening ahead.
Hello @Dave B your recommendations were correct. Thank you so much

Iniciar sesión para comentar.

Categorías

Más información sobre Climate Science and Analysis en Centro de ayuda y File Exchange.

Etiquetas

Preguntada:

el 10 de Oct. de 2021

Comentada:

el 17 de Oct. de 2021

Community Treasure Hunt

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

Start Hunting!

Translated by