taking mean of certain range ignorning NaN in matrix
6 views (last 30 days)
Show older comments
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 Comments
Adam
on 25 Sep 2014
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.
Accepted Answer
Andrei Bobrov
on 25 Sep 2014
Edited: Andrei Bobrov
on 6 Oct 2014
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 Comments
More Answers (2)
Adam
on 25 Sep 2014
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 Comments
Adam
on 25 Sep 2014
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
on 26 Sep 2014
Edited: Stephen23
on 6 Oct 2014
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
0 Comments
See Also
Categories
Find more on Creating and Concatenating Matrices in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!