4

I have a 34 x 1096 array that has NaN values.

 A = 
 NaN    0.2500     NaN    0.3750       NaN
 NaN    0.1100     NaN    0.4310     0.1250
 NaN    0.1250    0.2500  0.3750     0.4310

And I want

 A = 
0.2500   0.3750       NaN     NaN       NaN
0.1100   0.4310     0.1250    NaN       NaN
0.1250   0.2500     0.3750   0.4310     NaN     

Whats a simple way to do this?

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
user758114
  • 354
  • 5
  • 22
  • The bottom row has the most non-NaN value, and the top has the least non-Nan values. From top to bottom sometimes it gains a non-Nan value, sometimes the number of non-Nan values stays the same. – user758114 Apr 22 '14 at 16:43
  • Whops, thanks for answering. I've already deleted my question because I figured it out right after asking it, sorry. – Rafael Monteiro Apr 22 '14 at 16:44

3 Answers3

2
[~, jj] = sort(isnan(A), 2);
B = A(bsxfun(@plus, (1:size(A,1)).', (jj-1)*size(A,1)));
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
  • What's the `.'` doing? – Cape Code Apr 22 '14 at 17:04
  • @Jigg `.'` is just transposition – Luis Mendo Apr 22 '14 at 17:12
  • Ok, so it's equivalent to `'`? – Cape Code Apr 22 '14 at 17:13
  • @Jigg in this case (real numbers) yes. But `'` does a __complex conjugation__ in addition to transposition. I like to avoid an unnecessary conjugation using `.'` (even with real numbers). It also helps me remember that `'` is _not_ just transpose. With complex numbers the difference between `.'` and `'` is important! People seem to forget about it sometimes: see for example [here](http://stackoverflow.com/questions/22258444/transfer-function-in-time-domain) – Luis Mendo Apr 22 '14 at 17:15
  • @LuisMendo Maybe put that on your profile, so that you can direct people to the reason in future! :) – Divakar Apr 22 '14 at 17:33
  • @Divakar Yes, I thought of that when I saw chappjc's new profile... Maybe I will – Luis Mendo Apr 22 '14 at 17:37
  • I find it a bit counterintuitive. I guess it's my twisted logic to expect the simplest syntax to do the simplest stuff. – Cape Code Apr 22 '14 at 18:06
  • @Jigg Yes, it's not very intuitive. On the other hand, in certain contexts (matrix algebra) conjugate-and-tranpose may be "simpler", or at least more usual, than just transpose. – Luis Mendo Apr 22 '14 at 21:21
1

a simple way will be to use a for loop with ~isnan on each row, for example:

B=NaN(size(A));
for n=1:size(A,1)
    B(n,1:sum(~isnan(A(n,:))))=A(n,~isnan(A(n,:)));
end    

B =
0.2500    0.3750       NaN       NaN       NaN
0.1100    0.4310    0.1250       NaN       NaN
0.1250    0.2500    0.3750    0.4310       NaN

you can then assign A=B if you must... and yes this can be done without a for loop, but why bother in this case?

bla
  • 25,846
  • 10
  • 70
  • 101
  • Nice link. +1. But, as the text shows, there are still good reasons (though admittedly not so compelling) to avoid loops. – Luis Mendo Apr 22 '14 at 16:53
  • yea I agree, and that article is from 2012, so I'm TMW improved it's JIT in current releases. Also, don't get me wrong, there is great joy in vectorizing. But I've learned that for-loop are considered "simple" to understand, while `bsxfun` less so. – bla Apr 22 '14 at 18:53
1

Code

 A = [
 NaN    0.2500     NaN    0.3750       NaN
 NaN    0.1100     NaN    0.4310     0.1250
 NaN    0.1250    0.2500  0.3750     0.4310]

[M,N] = size(A)
[~,col1] = sort(~isnan(A),2,'descend')

row1 = repmat(1:M,N,1)'; %%//'
restructured_indices = sub2ind(size(A),row1(:),col1(:))
A = reshape(A(restructured_indices),M,N)

Output

A =
    0.2500    0.3750       NaN       NaN       NaN
    0.1100    0.4310    0.1250       NaN       NaN
    0.1250    0.2500    0.3750    0.4310       NaN
Divakar
  • 218,885
  • 19
  • 262
  • 358