taking mean of certain range ignorning NaN in matrix

I have a matrix Phi of size 500x359 with NaNs interspersed throughout. I need to take the column wise mean of the first 25 rows of non-NaN values for each column, but unlike nonmean() I dont want to consider rows with NaNs as rows at all. I want them to be skipped over completely. So I want to kinda of do the following nanmean(Phi(1:25)) where 1 is the first nonmean value regardless of its actual location in the matrix whether its the 1, 100, 200 etc and take the mean of the following 25 non-Nan values regardless of the location.
For example:
X=magic(4); X([1 3 7:9 14]) = repmat(NaN,1)
X =
NaN 2 NaN 13
5 11 10 NaN
NaN NaN 6 12
4 NaN 15 1
nanmean(X(1:2,3)) ans =
10
but what I want is (10+6)/2 = 8
and... so my end result would look like this...
phi_mean = [4.5000 6.5000 8 12.5000]
thank you

댓글 수: 5

nanmean(X(2:3,3))
would be what you want if you are selectively choosing just the two rows your expectation suggests you want.
That doesn't answer your bigger question, just the confusion of your example.
Stephen23
Stephen23 2014년 9월 25일
편집: Stephen23 2014년 9월 25일
This explanation is not very clear: "I dont want to consider rows with NaNs as rows at all. I want them to be skipped over completely", but in your example all of the rows of X contain NaN s, so should they all be "skipped over" ?
Yeah, I also found your example to actually be an example of something completely separate to your question which is why I initially got thrown off by just pointing out the obvious problem above before realising that was irrelevant to the actual question!
What I mean (and try to explain in my example) is the nanmean still considers the rows with NaN for indexing, but ignores them for actually taking the mean. What I need is to ignore the whole the NaN altogether. So for the example nanmean(X(1:2,3)) returns the mean of the first two rows, not the first two values, which is what I need. But in a large matrix I cant go through each row and select the first 25 values manually.
nanmean(X(1:2,3)) returns the mean of the first two values in the 3rd column, ignoring NaNs, but since that is just two values, one of which is a NaN it simply returns the second value of 10.

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

 채택된 답변

Andrei Bobrov
Andrei Bobrov 2014년 9월 25일
편집: Andrei Bobrov 2014년 10월 6일
nn = ~isnan(X);
ii = cumsum(nn).*nn;
out = mean(reshape(X(ii >= 1 & ii <= 25),25,[]));
other way
X = phidp;
k = 25;
ll = ~isnan(X);
[~,j0] = find(ll);
out = accumarray(j0,X(ll),[1 size(X,2)], @(x)mean(x(1:min(k,numel(x)))) );

댓글 수: 5

This seems like it would work but it gives me an error. As stated my matrix is 500x359, I only used the magic(4) to illustrate what I meant.
Error using reshape Product of known dimensions, 25, not divisible into total number of elements, 6136.
Andrei Bobrov
Andrei Bobrov 2014년 9월 25일
편집: Andrei Bobrov 2014년 9월 25일
see "other way" in my answer and please attach file with your array (500x359)
Hi, the second way worked! thank you. Also I didnt know you could attah the array to the question, will do next time.
Not sure if anyone will see this since I set thread as answered, but I found a problem with this "other way" method. if there is a column of all NaN this method ignores the whole column.
For example in the attached file when you apply this method the out becomes 355 long, instead of 359.
This is a problem because I need the length of the "out" to stay the same as the original matrix so I can remove the mean from the original value. I have attached a array if anyone has any ideas.
thanks
corrected

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

추가 답변 (2개)

Adam
Adam 2014년 9월 25일
hasNans = any( isnan(Phi), 2 );
validIdx = find( ~hasNans, 25 );
will give you the first 25 row indices which you can then use for your mean calculation.

댓글 수: 2

problem with that is that each column has a NaN in it somewhere so it just gives me an empty validIdx
It would probably help if you can give an example of what you actually want output to look like for a given small input that represents the problem you have, but on a small scale. The example you gave does not seem to do that and your explanation of what you want included the phrase 'I dont want to consider rows with NaNs as rows at all' which I took to mean that you wish to ignore all rows with a NaN anywhere in them. If that is the case then if every row has a NaN somewhere you would get an empty result.

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

Stephen23
Stephen23 2014년 9월 26일
편집: Stephen23 2014년 10월 6일
As far as I understand, you wish to calculate the mean of the first 25 non-NaN values in each column. This can be achieved easily using a couple of find calls. Using your example matrix X :
>> N = 2;
>> K = arrayfun(@(k)find(c==k,N),1:size(X,2),'UniformOutput',false);
>> K = horzcat(K{:});
>> [r,c] = find(~isnan(X));
>> mean(X(sub2ind(size(X),r(K),c(K))),1)
ans =
4.5 6.5 8 12.5
Or a much tidier solution is with some indexing:
>> N = 2;
>> Y = ~isnan(X);
>> mean(reshape(X(cumsum(Y,1)<=N & Y),N,[]),1)
ans =
4.5 6.5 8 12.5

카테고리

도움말 센터File Exchange에서 Logical에 대해 자세히 알아보기

질문:

2014년 9월 25일

편집:

2014년 10월 6일

Community Treasure Hunt

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

Start Hunting!

Translated by