Summing daily precipitation values into monthly totals using a for loop

4 次查看(过去 30 天)
NB: I've read some other posts on topics similar to this and tried out the suggestions in them, but am not getting the right results, so I asking for some troubleshooting advice.
I have a large precipitation data set (1.5 million observations spanning 94 years). The data set currently records daily observations (it's a 1.5 million x 4 matrix; columns are organized "Year", "Month", "Day", "Precipitation"). I would like to generate a new 12 (month) x 94 (year) data set where each cell is the sum of all precipitation observations in the original data set for that month in that particular year. I imagine that a for loop would enable me to do this, but when I set it up, all I get is a matrix full of zeroes. Here is the sample code. Any advice on where I'm going wrong?
theta = zeros(12, 94); % Zeroes matrix that contains rows equal to the number of months in data set (12) and columns equal to the number of years in the data set (94, 1923-2016).
% "tau" is a previously defined matrix that refers to the one containing the date and precipitation values; Column 1 = year, column 2 = month, column 3 = day, column 4 = precip. data. It has already been sorted by year and then by month.
for i = 1923:2016; % For each year from 1923-2016 (data set range)
if tau(:,2)==1; % Where the month column equals 1 (January),
theta(1,:) = sum(tau(:,4)); % Sum all values and place in row 1 of theta
elseif tau(:,2)==2; % Same as above, but for February
theta(2,:) = sum(tau(:,4)); % Place in row 2 of theta
elseif tau(:,2)==3; % March
theta(3,:) = sum(tau(:,4)); % Place in row 3 of theta
I continue all the way to December, but didn't want to copy and paste the whole code here. Last statement is an else statement rather than elseif.
I've also tried using accumarray, which other responses have suggested, but am not having any luck there either. Thanks in advance for your help.

回答(2 个)

Guillaume
Guillaume 2016-7-25
Using a for loop is a complete waste of time and using multiple if inside the loop even more. accumarray is indeed the answer.
Your requirements are a bit different than the usual in that you have to keys for the grouping, the year and the month, wherease usually both are grouped together into one key. No matter, it's not a problem for accumarray:
%input: matrix tau with year as first column, month as second, day as 3rd, and value as 4th
%the matrix does not need to be sorted, unique will do the sorting anyway
[months, ~, destrow] = unique(tau(:, 2)); %find row destination of month of each entry in tau
[years, ~, destcol] = unique(tau(:, 1)); %find column destination of year of each entry in tau
theta = accumarray([destrow, destcol], tau(:, 4))
  2 个评论
Laura West
Laura West 2016-7-25
Thank you for your suggestion. I appreciate your help. However, when I input the code you provided, I get an error message saying that the requested matrix ("theta") exceeds maximum array size preference.
Guillaume
Guillaume 2016-7-25
编辑:Guillaume 2016-7-25
What is
max(destrow)
max(destcol)
The first one should be 12, the second 94. Therefore, accumarray should generate a 12x94 matrix, which is far below maximum array size
If that is not the case, something is not right with your description. In that case, attach your tau matrix as a mat file.
edit: testing the code with dummy data:
tau = [randi([1923 2016], 1500000, 1), ... random year between 1923 and 2016
randi([1 12], 1500000, 1), ... random month
randi([1 30], 1500000, 1), ... random day
randi(1, 1500000)] %dummy tau with 1.5 million rows
[months, ~, destrow] = unique(tau(:, 2));
[years, ~, destcol] = unique(tau(:, 1));
theta = accumarray([destrow, destcol], tau(:, 4))
works perfectly fine on my machine and results in a 12x94 matrix. Your tau is not as described.

请先登录,再进行评论。


Nathan Dick
Nathan Dick 2017-4-2
编辑:Nathan Dick 2017-4-2
Hi Guillaume
I have had to do the same thing as Laura and the code worked perfectly. I am just trying to understand what you are saying in this section of your code:
[months, ~, destrow] =
I have tried changing to variable = unique(A(:,a)) and it doesnt work due to this error:
Error using horzcat
Dimensions of matrices being concatenated are not consistent.
Error in IrrWaterBalance (line 21)
MonPdat = accumarray([destrow, destcol], Data(:, 1));
I know this is an old thread but I like to understand what the code is saying if using it.
Kind Regards
Nathan
  1 个评论
Guillaume
Guillaume 2017-4-3
Really, you ought to start your own question rather than asking your question as an answer.
The error message is due to the fact that destrow and destcol don't have the same number of elements. The number of rows in each is the number of rows in the matrix you're passing to unique, so if they're different, you've used different matrices.
I don't understand your question about the
[months, ~, destrow] = ...
The months variable is not strictly required. It corresponds to each row of the final matrix. destrow is the important variable. It transform the original matrix in a vector from 1 to the number of uniques values in that matrix.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Logical 的更多信息

Community Treasure Hunt

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

Start Hunting!

Translated by