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에서 Logical에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by