Asked by mfclose
on 19 Jul 2019

I am trying to:

1) Identify the first non-NaN value of each column in an array, and convert the rest to NaN

2) Identify the first non-NaN value of each row in the array, and convert the rest to NaN

3) Combine these numbers back into one column vector

I have created something that looks roughly like this (although much larger):

X =

2 NaN NaN NaN

4 6 NaN NaN

NaN NaN NaN NaN

5 4 7 8

After the first step (keeping only the first number in each column), I would hope to have this:

Xa =

2 NaN NaN NaN

NaN 6 NaN NaN

NaN NaN NaN NaN

NaN NaN 7 8

After the second step (keeping only the first number in each row), I would hope to have this:

Xb =

2 NaN NaN NaN

NaN 6 NaN NaN

NaN NaN NaN NaN

NaN NaN 7 NaN

Lastly, I would want to turn this into one column (there should only be NaN's or 1 non-NaN value in each row - I would want it to keep whichever is there)

Xc =

2

6

NaN

7

I apologize for not having any attempted code for this. I appear to have gotten stuck in the doorway of this one...

Answer by Bruno Luong
on 19 Jul 2019

Edited by Bruno Luong
on 19 Jul 2019

Accepted Answer

X = [2 NaN NaN NaN;

4 6 NaN NaN;

NaN NaN NaN NaN;

5 4 7 8 ]

[m,n] = size(X);

[I,J] = ndgrid(1:m,1:n);

Xa = X;

[~,r]=max(isfinite(Xa),[],1);

Xa(I>r) = NaN

Xb = Xa;

[~,c]=max(isfinite(Xb),[],2);

Xb(J>c) = NaN

[~,c]=max(isfinite(Xb),[],2);

Xc = Xb(sub2ind([m,n],(1:m)',c))

Answer by Adam Danz
on 19 Jul 2019

Edited by Adam Danz
on 19 Jul 2019

X = [2 NaN NaN NaN

4 6 NaN NaN

NaN NaN NaN NaN

5 4 7 8];

X(cumsum(cumsum(~isnan(X)))~=1) = NaN; % your Xa

X(cumsum(cumsum(~isnan(X),2),2) ~=1) = NaN; % your Xb

Xc = NaN(size(X,1),1);

Xc(any(~isnan(X),2)) = X(~isnan(X)); % your Xc

mfclose
on 19 Jul 2019

Thank you this also worked!

Adam Danz
on 19 Jul 2019

Sign in to comment.

Answer by Mario Chiappelli
on 19 Jul 2019

Check out this question asked earlier on the forum, I think it asks and answers what you want.

mfclose
on 19 Jul 2019

Thank you for this!

It is a similar question. Some of the differences that are proving problematic for me are that:

1) I only want the first non-NaN value, not all of them

2) I don't want to lose the row position that each of these values have (as that represents a time point I will need to compare back to later), so if there is only ever a NaN in a row, I need to keep that there (like in the 3rd row of Xc in my example)

These may only be subtle differences, but I'm not quite sure how to make those adjustments. Thanks for your help!

Mario Chiappelli
on 19 Jul 2019

Try this:

x = [2,NaN,NaN,NaN;4,6,NaN,NaN;NaN,NaN,NaN,NaN;5,4,7,8];

rows = length(x(:,1));

columns = length(x(1,:));

% This finds the first non NaN in the columns

columnVector = double(columns);

for i = 1:columns

found = 0;

for j = 1:rows

if ~isnan(x(j,i)) && found == 0

found = 1;

columnVector(i) = x(j,i);

end

end

if found == 0

columnVector(i) = NaN;

end

end

% This finds the first non NaN in the rows

rowVector = double(rows);

for i = 1:rows

found = 0;

for j = 1:columns

if ~isnan(x(i,j)) && found == 0

found = 1;

rowVector(i) = x(i,j);

end

end

if found == 0

rowVector(i) = NaN;

end

end

I could include some more functionality to delete any NaN values in the resulting columnVector and rowVector arrays. This does what you want, however it skips over the middle steps. I did not know if that was a necessary step for you or just your way of visualizing what needed to be done.

Hope this helps :)

mfclose
on 19 Jul 2019

Sign in to comment.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.