Effacer les filtres
Effacer les filtres

taking mean of certain range ignorning NaN in matrix

4 vues (au cours des 30 derniers jours)
Brandon
Brandon le 25 Sep 2014
Modifié(e) : Stephen23 le 6 Oct 2014
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 commentaires
Brandon
Brandon le 25 Sep 2014
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.
Adam
Adam le 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.

Connectez-vous pour commenter.

Réponse acceptée

Andrei Bobrov
Andrei Bobrov le 25 Sep 2014
Modifié(e) : Andrei Bobrov le 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 commentaires
Brandon
Brandon le 6 Oct 2014
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
Andrei Bobrov
Andrei Bobrov le 6 Oct 2014
corrected

Connectez-vous pour commenter.

Plus de réponses (2)

Adam
Adam le 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 commentaires
Brandon
Brandon le 25 Sep 2014
problem with that is that each column has a NaN in it somewhere so it just gives me an empty validIdx
Adam
Adam le 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.

Connectez-vous pour commenter.


Stephen23
Stephen23 le 26 Sep 2014
Modifié(e) : Stephen23 le 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

Catégories

En savoir plus sur Creating and Concatenating Matrices dans Help Center et File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by