more efficient way of using for loop?

1 Ansicht (letzte 30 Tage)
Roisin Loughnane
Roisin Loughnane am 3 Okt. 2017
Kommentiert: Guillaume am 3 Okt. 2017
Hello everyone. I am new to Matlab and would really appreciate your help. I have a time series of multiple years of environmental data, which I would like to group together (here as a 3D array), get the mean and then save the mean output file for each month. My files are named by (datatype)_(year)_(month).asc
I attempted this by looping over the years and loading corresponding monthly files:
years = {'2003' '2004' '2005' '2006' '2007' '2008' '2009' '2010' '2011' '2012' '2013' '2014'}
%%January
for y = 1:length(years)
filename = strcat('sst_',num2str(years{y}),'_1.asc');
% read file in as array
load(filename)
end
and then concatenate the arrays, get the mean and save the output mean sea surface temperature file:
sst_climatology_1 = cat(12, sst_2003_1, sst_2004_1, sst_2005_1, sst_2006_1, sst_2007_1, sst_2008_1, sst_2009_1, sst_2010_1, sst_2011_1, sst_2012_1, sst_2013_1, sst_2014_1);
msst_1 = mean(sst_climatology_1,12);
dlmwrite('msst_1.csv',msst_1)
This is fine but obviously doing this 12 times for each month is ugly and unnecessary when I am sure there is a simple for loop or otherwise solution. Can somebody please point any solutions out to me please?
  1 Kommentar
Stephen23
Stephen23 am 3 Okt. 2017
Bearbeitet: Stephen23 am 3 Okt. 2017
load-ing directly into the workspace is great fun from the command line, but should be avoided when writing real code, if you want it to be efficient and reliable:
You would avoid all of that awkward playing around lots of variables if you simply loaded into one variable.

Melden Sie sich an, um zu kommentieren.

Antworten (1)

Guillaume
Guillaume am 3 Okt. 2017
Bearbeitet: Guillaume am 3 Okt. 2017
A few things:
  • Creating your years cell array could be achieved more simply with:
years = compose('%d', 2003:2014);
  • but since you're constructing your filename using num2str (which at present does nothing since years{y} is already a string), then you could just store it as an array of numbers:
years = 2003:2014;
  • the first output of cat is not the number of matrices you concatenate, but in which dimension you concatenate, regardless of their number. If your sst_... matrices are 2D, then cat(3, ...) makes a lot more sense than cat(12, ...)
The main difficulty comes from the fact that you're using load without assigning its output, popping variables with varying name into existence. Giving an output to load would make your life easier. Here is how I would do it:
years = 2003:2014;
monthlydata = cell(1, numel(years)); %to hold the monthly data of each year. Preallocated.
for month = 1:12
for y = 1:numel(years)
monthlydata{y} = load(sprintf('sst_%d_%d.asc', years(y), month)); %load year_month into cell of cell array
end
monthlydata = cat(3, monthlydata{:}); %concatenate all cells along 3rd dimension
monthlymean = mean(monthlydata, 3); %get mean
dlmwrite(sprintf('msst_%d.csv', month), monthtlymean); %save
end
  3 Kommentare
Roisin Loughnane
Roisin Loughnane am 3 Okt. 2017
I figured it out:
The cell monthlydata was being changed to a class double outside the inner loop, so I just changed the name
monthlydatac = cat(3, monthlydata{:});
monthlymean = mean(monthlydatac, 3);
Guillaume
Guillaume am 3 Okt. 2017
That error can only come from the line
monthlydata{y} = ...
and only if monthlydata already exists and is not a cell array, which can't be the case if you've preallocated it with the line:
monthlydata = cell(1, numel(years));
Therefore the only way you get this error is if you haven't included that line.

Melden Sie sich an, um zu kommentieren.

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by