How to obtain average in a matrix without loop?

In matrix A, I want to create a new column that contains the yearly average of the 5th column for each stations. The columns from left to right are: station, year, month, day, value. I want to avoid loops if possible.
A= [10 2000 1 1 1.5;
10 2000 1 3 1.1;
...
20 2000 1 1 1.2;
20 2000 1 2 1.4;
...
10 2001 1 1 1.1;
10 2001 1 4 1.3;
...
]
B= [10 2000 1 1 1.5 1.2;
10 2000 1 3 1.1 1.2;
...
20 2000 1 1 1.2 1.4;
20 2000 1 2 1.4 1.4;
...
10 2001 1 1 1.1 1.1;
10 2001 1 4 1.3 1.1;
...
]
so I want to make B in which the 6th column is yearly average of 5th column for each station.
thanks!

댓글 수: 6

Jan
Jan 2012년 9월 6일
편집: Jan 2012년 9월 6일
Why do you want to avoid loops? At least a loop over the stattions would decrease the complexity of the code substantially. Some Matlab programmers use the avoidance of loops as a mantra without any real benefit since the JIT has been introduced in Matlab 6.5. As long as I do not see a good reason to avoid FOR loops, I'm not going to struggle with ACCUMARRAY. It is not worth to spend 5 minutes programming time only to save some microseconds of runtime.
The 4th column is the "day". Do you want the average of the 5th column? But even then: (1.5 + 1.1) / 2 ~= 1.2. Thefore please explain, what you want to calculate.
FATEMEH
FATEMEH 2012년 9월 6일
sorry.yes, I want the average of the 5th. I,m not that familiar with the details. I just wanted to avoid loops to save time, but If there is no other way or the codes get complicated, I can use loops.
@Jan - that's why I love accumarray!! It's usually slower than a for-loop but it saves me a few minutes writing the same generic for-loops over and over again :)
@Sean: I've read the docs 8 times, and I'm still missing the "click". At least when I reach the 2nd section, I give up:
A = accumarray(subs,val,sz) creates an array A with size sz, where sz is a vector of positive integers. If subs is nonempty with N>1 columns, then sz must have N elements, where all(sz >= max(subs,[],1)). If subs is a nonempty column vector, then sz must be [M 1], where M >= MAX(subs). Specify sz as [] for the default behavior.
I'm convinced, that this is meaningful and most likely even clear and trivial. But I do not understand anything of it - in opposite to all other help and doc textes of Matlab. When I read http://blogs.mathworks.com/loren/2008/02/20/under-appreciated-accumarray, I see that I'm not alone:
Eris S wrote: I think that ACCUMARRAY has one of the worst documentation pages in MATLAB. I also find ACCUMARRY to be probably the number one most confusing function in MATLAB – there might be causation behind this correlation ;)
It means that you can fix the end result size if you want it to be bigger in the event that subs does not cover data at that size.
Let's say I have:
x = accumarray([1;2;1],ones(3,1))
But I always want the result to be 5x1 even if I don't have any 5s in my subs vector:
x = accumarray([1;2;1],ones(3,1),[5 1])
How could this be useful?
f() expects x to be a 5x1. I pull unique values from another vector but it turns out that there are only four unique values. The first implementation will return a 4x1 and would break f().
I concur, Jan! Every time I know intuitively that ACCUMARRAY would work in a given situation, I have to re-read the doc. Then I have to work through a few of the doc examples to remember how to interpret what the doc says. Then I can proceed to use the function, if I am lucky and don't have to re-read the doc. And English is my native tongue (I can't imagine trying to figure this function out otherwise)!
It is a useful function, but I usually spend more time trying to figure out how to apply it to the problem at hand as I would just writing the FOR loops. I cannot tell you how many times I have seen this error message:
Error using accumarray
Second input VAL must be a vector with one element for each row in SUBS, or a scalar.
It is one of the few MATLAB error messages I have memorized and that I expect to see the first time I try that function on a given day.

댓글을 달려면 로그인하십시오.

 채택된 답변

Sean de Wolski
Sean de Wolski 2012년 9월 6일

1 개 추천

A= [10 2000 1 1 1.5;
10 2000 1 3 1.1;
20 2000 1 1 1.2;
20 2000 1 2 1.4;
10 2001 1 1 1.1;
10 2001 1 4 1.3];
[~,~,idxA] = unique(A(:,1:2),'rows');
means = accumarray(idxA,A(:,4),[],@mean);
B = [A means(idxA)]
But your example does not actually make it look like B contains the means of column four for the unique combinations of columns 1/2.

댓글 수: 2

Jan
Jan 2012년 9월 6일
Perhaps "A(:,4)" -> "A(:,5)", but this will not create B also.
FATEMEH
FATEMEH 2012년 9월 6일
thanks to both of you. Fatemeh

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

도움말 센터File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by