How to convert 3d monthly data into season

Example of my data set is 56*42*360 (30 years) and each page represent a month for example 56*42*1 mean jan 1980 and 56*42*13 means jan 1981. I want to get only seasonal value not the number of months in a season, we have to define season as spring(mar, apr ,may), summer(jun,jul,aug) and so on.
I found a relevant solution here but it gives only number of months of a single season. I need seasons in staright as spring of 1980.......to autumn of 2010.
Expected outcome is something like 56*42*119.

2 Comments

And how do you convert 3 months into a season? sum all the data? Take the mean, median, mode or something else?
Once we know that, performing the grouping is trivial.
Dear Guillaume,I would like to make season with sum of monthly values.

Sign in to comment.

 Accepted Answer

How about the following?
% Sample data
Data = rand(56,42,360);
% Reshape the data so that each row shows monthly data (42*56)
Data = permute(Data,[3 2 1]);
Data = reshape(Data,360,42*56);
% Calculate sum for evely 3 months
group = repelem((1:120)',3);
Data2 = splitapply(@sum,Data, group);
% Reshape the data to the original format
Data2 = reshape(Data2,120,42,56);
Data2 = permute(Data2,[3 2 1]);

6 Comments

Thank you for your response.
It is working well for normal array but my intended is a spatial data and it we change the matrix into line then whole spatial (latitude and longitude) arrange mess up, it gives very strange output.
I must have to keep the arrangment of (x(56), y(42)) as given becasue each cell represent unique value that specific location.
You mena, your 56 x 42 x 360 data is stored as an cell array? If possible, could you upload your data as a mat file here?
yes Akira,
I uploaded a sample data 56*42*204 here, have a look.
Again I do not want to change the arrangment of 56*42 and only need to sum every 3 pages of third dimension (204). The expected output should something like 56*42*68.
test.jpg
Thank you for uploading your data.
Looking at your data, I believe my previous strategy should work.
For example, the following code generates 56*42*68 data3, and I think this should be what you want as an output.
load('data.mat');
sz = size(data);
data2 = permute(data,[3 2 1]);
data2 = reshape(data2,sz(3),sz(2)*sz(1));
group = repelem((1:sz(3)/3)',3);
data3 = splitapply(@sum,data2,group);
data3 = reshape(data3,sz(3)/3,sz(2),sz(1));
data3 = permute(data3,[3 2 1]);
Note that to account for the fact that the 1st season is incomplete, and last one may be as well, you may need to create group slightly differently.
group = repelem((1:ceil((sz(3)+1)/3))', 3);
group = group(2:sz(3)+1);
Thank you Akira and Guillaume for help.

Sign in to comment.

More Answers (1)

Guillaume
Guillaume on 4 Mar 2019
Edited: Guillaume on 4 Mar 2019
I don't see anything wrong with Akira's approach. It does what is asked (except that it has a wrong start of season).
However, I'd use a different approach. I'd simply reshape into an Mx3xS (where M is data points per month and S is number of seasons) and sum across the columns. You may need to add some extra months full of 0 (which don't affect the sum) to make sure that we've got 3 months for all seasons.
So, if the matrix starts in January and ends in December, we need to add one month of 0s at the start and 2 months of 0s at the end:
%data: a 3D matrix whose 3rd dimension is a month. It is assumed that first month is January
padded = cat(3, zeros(size(data, 1), size(data, 2), 'like', data), data); %prepend december of previous year to complete first season
padded = cat(3, padded, zeros(size(data, 1), size(data, 2), mod(-size(padded, 3), 3), 'like', data)); %append however months is necessary (0-1-2) to finish last season
seasonal = reshape(padded, size(data, 1) * size(data, 2), 3, []); %each column is a whole month, with 3 columns, each page is a season
seasonalsum = sum(seasonal, 2); %sum months within a season
seasonalsum = reshape(seasonalsum, size(data, 1), size(data, 2), []); %and reshape into original 3D shape
edit: Note that I'm padding with 0s since it doesn't affect the sum. If you were to calculate the mean or some other statistics, I'd pad with NaNs instead, and use the 'omitnan' option of the corresponding function. You could do that for the sum as well.

Categories

Products

Release

R2014a

Tags

Community Treasure Hunt

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

Start Hunting!