calculate mean of 4D array
Show older comments
I have 41 years monthly data of temperature (lat,lon,depth,time,temperature). I wanted to calculate annual mean and seasonal mean [(summer: Dec, Jan, Feb), (autumn: Mar, Apr, May), (winter = Jun, Jul, Aug), (spring = Sep, Oct, Nov)] of each grid, eache depth level for the period of 1982-2022.
2 Comments
Paul
on 11 May 2024
Hi @Gurumoorthi K.,
You're more likely to get help if you upllad your data (or something like it) in .mat file using the Paperclip icon on the Insert menu so that people can see exactly how the data is organized.
Gurumoorthi K
on 11 May 2024
Moved: Voss
on 11 May 2024
Accepted Answer
More Answers (1)
Kris Fedorenko
on 27 Jan 2026
Edited: Kris Fedorenko
on 27 Jan 2026
I know this is an old post, but I was curious and taking a look at it anyway, so I thought I'd post my stab at it just in case.
Would have been great to have the data attached. I wasn't able to find exactly the same data, but I found similar one at https://www.metoffice.gov.uk/hadobs/en4/download-en4-2-2.html . I only downloaded data for years 2021 and 2022 (for all the months).
In my approach I first concatenate all the temperature data into longitude-by-latitude-by-depth-by-date matrix, so this is more memory-intensive than the other proposed solution. But this would be useful if there is need to calculate any other statistics over the same data.
ncFiles = dir('*.nc');
% this will be dimension vector for the 4th dimension (dates)
dates = NaT(length(ncFiles),1);
temperatures = [];
for i = 1:length(ncFiles)
filename = ncFiles(i).name;
% extract date from filename and add it to the dimension vector
[~, dateText, ~] = fileparts(filename);
dates(i) = datetime(dateText, InputFormat="yyyyMM");
% alternatively extract date from the file
% daysSince1800_01_01 = ncread(filename, "time");
% dates(i) = datetime(1800, 01, 01) + days(daysSince1800_01_01);
% extract longitudes from the file (dimension vector for 1st dimension)
curLons = ncread(filename, "lon");
% check if longitudes are the same in each file;
% might be unnecessary if we can already assume that.
if i==1
longitudes = curLons;
else
assert(isequal(longitudes, curLons), "Longitudes are not the same in all files")
end
% extract latitudes from the file (dimension vector for 2nd dimension)
curLats = ncread(filename, "lat");
% check if latitudes are the same in each file;
% might be unnecessary if we can already assume that.
if i==1
latitudes = curLats;
else
assert(isequal(latitudes, curLats), "Latitudes are not the same in all files")
end
% extract depths from the file (dimension vector for 3rd dimension)
curDeps = ncread(filename, "depth");
% check if depths are the same in each file;
% might be unnecessary if we can already assume that.
if i==1
depths = curDeps;
else
assert(isequal(depths, curDeps), "Depths are not the same in all files")
end
% extract temperature and concatenate it all together
% (along 4th demension)
curTemp = ncread(filename, 'temperature'); % lon x lat x depth x time
temperatures = cat(4, temperatures, curTemp);
end
Now that we have all temperature data in one matrix and also the dimension vectors for Longitude, Latitude, Depth, and Date, we can calculate any needed statistic from it (like the mean for any given year). We can also extract data for any specific Lat-Long-Depth grid point. For example:
% yearly mean for 2021 (for each lat-lon-depth grid)
mean2021 = mean(temperatures(:,:,:, dates.Year==2021), 4); % mean over dates (4th dim), the result is long x lat x depth
% 2021 yearly mean for Latitude = 71, Longitude = 42, at Depth closest to 15 meters
[~, closestInd] = min(abs(depths-15));
mean2021(longitudes==42, latitudes==71, closestInd) % ~277.4722 Kelvin
% summer mean over all years
summer = [12, 1, 2]; % Dec, Jan, Feb - summer months in southern hemisphere
meanSummers = mean(temperatures(:,:,:, ismember(dates.Month, summer)), 4);
% summer mean for Latitude = 71, Longitude = 42, at Depth(s) close to 110 meters
meanSummers(longitudes==42, latitudes==71, isapprox(depths, 110, "veryloose")) % ~275.1186 Kelvin
% plot summer mean for Latitude = 71, Longitude = 42, at all depths
meanSummersAtCoords = squeeze(meanSummers(longitudes==42, latitudes==71, :)); % depth x 1
plot(depths, meanSummersAtCoords, 'x-')
title('Mean temperature over Jan, Feb, Dec months 2021-2022 at 71 N, 42 E')
xlabel("Depth (meters)")
ylabel("Temperature (Kelvin)")

Alternatively, you could also flatten the data into a timetable and calculate any needed statistics using groupsummary or rowfun (for an example of a timetable approach see https://uk.mathworks.com/matlabcentral/answers/2176414-era5-average-hourly-data-and-yearly-data?s_tid=srchtitle ).
Categories
Find more on Visualization and Analytics in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!