How to interpolate NaN values

I have Matrix A as:
A = [4 5 9 Nan 8 3 4 4
3 5 9 7 8 3 4 4
4 4 5 8 6 5 4 4
4 5 9 Nan 8 3 4 4
3 5 1 Nan 5 4 9 1
7 2 2 8 5 5 6 1
3 4 1 2 5 4 9 8
3 5 1 4 1 1 1 9
3 4 5 2 3 4 6 6
3 4 5 Nan 3 4 6 6];
There are some NaN values in column 4. I want to find similar rows in matrix A and give relevant value of their column 4 to those NaN cells. In case if all cells in a row aren't matching with the row of Nan, find the most matchable (perhaps weighting option).
Results can be similar to B:
B = [4 5 9 7 8 3 4 4
3 5 9 7 8 3 4 4
4 4 5 8 6 5 4 4
4 5 9 7 8 3 4 4
3 5 1 2 5 4 9 1
7 2 2 8 5 5 6 1
3 4 1 2 5 4 9 8
3 5 1 4 1 1 1 9
3 4 5 2 3 4 6 6
3 4 5 2 3 4 6 6];
% first and fourth rows Nan values got value 7 from second row because of most similarity % fifth row Nan value got value 2 from the seventh row because of most similarity % tenth row Nan value got value 2 from the ninth row because of exact similarity

 Accepted Answer

Stephen23
Stephen23 on 9 Sep 2018
Edited: Stephen23 on 9 Sep 2018
>> X = isnan(A(:,4));
>> C = [1:3,5:8];
>> D = sum(bsxfun(@minus,permute(A(~X,C),[1,3,2]),permute(A(X,C),[3,1,2])).^2,3);
>> [~,Y] = min(D,[],1);
>> Z = find(~X);
>> A(X,4) = A(Z(Y),4)
A =
4 5 9 7 8 3 4 4
3 5 9 7 8 3 4 4
4 4 5 8 6 5 4 4
4 5 9 7 8 3 4 4
3 5 1 8 5 4 9 1
7 2 2 8 5 5 6 1
3 4 1 2 5 4 9 8
3 5 1 4 1 1 1 9
3 4 5 2 3 4 6 6
3 4 5 2 3 4 6 6
>> Z(Y) % the rows used
ans =
2
2
6
9

5 Comments

Thanks @Stephen Cobeldick. Do you know why some rows are being replaced? For example, an extra column was added at the end (as sorting number) and as you can see some rows are missing (#1,#4,#5,#10) in the result. Are you able to keep all original rows and just update rows with NaN value?
A = [4 5 9 nan 8 3 4 4 1
3 5 9 7 8 3 4 4 2
4 4 5 8 6 5 4 4 3
4 5 9 nan 8 3 4 4 4
3 5 1 nan 5 4 9 1 5
7 2 2 8 5 5 6 1 6
3 4 1 2 5 4 9 8 7
3 5 1 4 1 1 1 9 8
3 4 5 2 3 4 6 6 9
3 4 5 nan 3 4 6 6 10];
And after code run:
A = [3 5 9 7 8 3 4 4 2
3 5 9 7 8 3 4 4 2
4 4 5 8 6 5 4 4 3
3 5 9 7 8 3 4 4 2
7 2 2 8 5 5 6 1 6
7 2 2 8 5 5 6 1 6
3 4 1 2 5 4 9 8 7
3 5 1 4 1 1 1 9 8
3 4 5 2 3 4 6 6 9
3 4 5 2 3 4 6 6 9]
@Lu Xi: sorry, I misinterpreted your original question to mean that you wanted to replace the whole row, but now I see that you only want to replace the NaN in column 4. This is easy to do, just change the last line of my answer to this:
A(X,4) = A(Z(Y),4)
To ignore the last column when making the comparison you should also define C like this:
C = [1:3,5:8];
This is the output when I made those two changes and try your new matrix:
A =
4 5 9 7 8 3 4 4 1
3 5 9 7 8 3 4 4 2
4 4 5 8 6 5 4 4 3
4 5 9 7 8 3 4 4 4
3 5 1 8 5 4 9 1 5
7 2 2 8 5 5 6 1 6
3 4 1 2 5 4 9 8 7
3 5 1 4 1 1 1 9 8
3 4 5 2 3 4 6 6 9
3 4 5 2 3 4 6 6 10
Thanks @Stephen Cobeldick for corrections and extra note. It's very close to what I am looking for. Is there any alternative function to replace bsxfun function. Because when I use a larger input, I am getting the following error:
Error using bsxfun
Requested 126074x2459x7 (16.2GB) array exceeds maximum array size preference. Creation of arrays greater than this limit
may take a long time and cause MATLAB to become unresponsive. See array size limit or preference panel for more
information.
@Lu Xi: for such a large matrix A you can use a loop, and check one NaN row on each iteration:
X = isnan(A(:,4));
C = [1:3,5:8];
Z = find(~X);
for k = reshape(find(X),1,[])
[~,Y] = min(sum(bsxfun(@minus,A(~X,C),A(k,C)).^2,2));
A(k,4) = A(Z(Y),4);
end
Giving:
A =
4 5 9 7 8 3 4 4 1
3 5 9 7 8 3 4 4 2
4 4 5 8 6 5 4 4 3
4 5 9 7 8 3 4 4 4
3 5 1 8 5 4 9 1 5
7 2 2 8 5 5 6 1 6
3 4 1 2 5 4 9 8 7
3 5 1 4 1 1 1 9 8
3 4 5 2 3 4 6 6 9
3 4 5 2 3 4 6 6 10
Excellent @Stephen Cobeldick!

Sign in to comment.

More Answers (0)

Asked:

on 9 Sep 2018

Commented:

on 9 Sep 2018

Community Treasure Hunt

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

Start Hunting!