1

I have an array A (m X n) and another W (m X n'), where n' <= n. W can contain nan entries.

I want to set the first n' columns of A with W. However, at the positions where W has a nan, I want original A entries to be preserved.

Here is a sample code.

In [1]: import numpy as np

In [2]: A = np.random.rand(10, 4)

In [3]: A
Out[3]: 
array([[ 0.60879191,  0.13556633,  0.26043647,  0.69874723],
       [ 0.23775325,  0.5744113 ,  0.76446265,  0.82177711],
       [ 0.44320766,  0.43535148,  0.33745034,  0.63270876],
       [ 0.81903997,  0.15170996,  0.9847644 ,  0.77856538],
       [ 0.89771006,  0.11521106,  0.92180393,  0.82296974],
       [ 0.57292616,  0.47236245,  0.643821  ,  0.39011254],
       [ 0.1478904 ,  0.1597816 ,  0.61934679,  0.87229069],
       [ 0.6395053 ,  0.40529633,  0.02389057,  0.0144438 ],
       [ 0.25381449,  0.28045816,  0.98475699,  0.03257699],
       [ 0.91827695,  0.85382925,  0.94231584,  0.5303724 ]])

In [4]: W = np.random.rand(10, 2)

In [5]: W
Out[5]: 
array([[ 0.85731947,  0.02603337],
       [ 0.46941828,  0.12485814],
       [ 0.607665  ,  0.61742206],
       [ 0.67579577,  0.44169912],
       [ 0.77938579,  0.04609614],
       [ 0.55431149,  0.12936694],
       [ 0.05191665,  0.94768561],
       [ 0.9494111 ,  0.21739947],
       [ 0.77785379,  0.35316779],
       [ 0.72959474,  0.72603156]])

In [6]: W[2, 1] = np.NAN

In [7]: W[4, 0] = np.NAN

In [8]: W
Out[8]: 
array([[ 0.85731947,  0.02603337],
       [ 0.46941828,  0.12485814],
       [ 0.607665  ,         nan],
       [ 0.67579577,  0.44169912],
       [        nan,  0.04609614],
       [ 0.55431149,  0.12936694],
       [ 0.05191665,  0.94768561],
       [ 0.9494111 ,  0.21739947],
       [ 0.77785379,  0.35316779],
       [ 0.72959474,  0.72603156]])

In [9]: W_non_nan = ~np.isnan(W)

In [10]: W_non_nan
Out[10]: 
array([[ True,  True],
       [ True,  True],
       [ True, False],
       [ True,  True],
       [False,  True],
       [ True,  True],
       [ True,  True],
       [ True,  True],
       [ True,  True],
       [ True,  True]], dtype=bool)

In [11]: A[W_non_nan]

Out[11]: 
array([ 0.60879191,  0.13556633,  0.23775325,  0.5744113 ,  0.44320766,
        0.81903997,  0.15170996,  0.11521106,  0.57292616,  0.47236245,
        0.1478904 ,  0.1597816 ,  0.6395053 ,  0.40529633,  0.25381449,
        0.28045816,  0.91827695,  0.85382925])

Barring A[2, 1] and A[4, 0]; the first two columns of A should be replaced with W. What's the cleanest way to do so?

2 Answers 2

1

You can use masking/boolean-indexing with a mask of non-NaNs sliced into the first n' columns and use that mask for both selecting elements off W and assigning into the sliced portion of A, like so -

mask = ~np.isnan(W)
A[:,:mask.shape[1]][mask] = W[mask]

Sample run -

In [121]: A
Out[121]: 
array([[ 68.,  54.,  54.,  15.],
       [ 50.,  86.,  84.,  74.],
       [ 27.,  39.,  43.,  24.],
       [ 41.,  45.,  42.,  40.],
       [ 32.,  90.,  93.,  19.]])

In [122]: W
Out[122]: 
array([[  3.,   4.],
       [  3.,   1.],
       [  4.,  nan],
       [  6.,   8.],
       [ nan,   6.]])

In [123]: mask = ~np.isnan(W)

In [124]: A[:,:mask.shape[1]][mask] = W[mask]

In [125]: A
Out[125]: 
array([[  3.,   4.,  54.,  15.],
       [  3.,   1.,  84.,  74.],
       [  4.,  39.,  43.,  24.],
       [  6.,   8.,  42.,  40.],
       [ 32.,   6.,  93.,  19.]])
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. Super useful!
1

An alternative solution:

A = np.array([[ 68.,  54.,  54.,  15.],
       [ 50.,  86.,  84.,  74.],
       [ 27.,  39.,  43.,  24.],
       [ 41.,  45.,  42.,  40.],
       [ 32.,  90.,  93.,  19.]])

W = np.array([[  3.,   4.],
       [  3.,   1.],
       [  4.,  np.nan],
       [  6.,   8.],
       [ np.nan,   6.]])   
#replace first two cols of A with W except the positions where W has nan.    
A[:,0:2] = np.where(np.isnan(W),A[:,0:2],W)
print(A)

[[  3.   4.  54.  15.]
 [  3.   1.  84.  74.]
 [  4.  39.  43.  24.]
 [  6.   8.  42.  40.]
 [ 32.   6.  93.  19.]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.