How to change values in matrix to corresponding row value in vector based on condition
Question:
I’m interested in whether it’s possible do the following with pure numpy.
Let’s say I have a matrix a and a vector b. I want to fill whatever values meet the condition to the left of the equal sign with the value from the vector b correponding to the row in matrix a.
import numpy as np
a = np.arange(30).reshape(5,6)
a[3,3] = 2
a[4,0] = 1
a
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 2, 22, 23],
[ 1, 25, 26, 27, 28, 29]])
b = np.arange(0,5)[:,None]
b
array([[0],
[1],
[2],
[3],
[4]])
a[a<3] = b
TypeError: NumPy boolean array indexing assignment requires a 0 or 1-dimensional input, input has 2 dimensions
I understand why this doesn’t work and that I would need to reshape b to the same shape as a, and then subset it by a<3 first
b_mat = np.full(a.shape, b)
a[a<3] = b_mat[a<3]
a
array([[ 0, 0, 0, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 3, 22, 23],
[ 4, 25, 26, 27, 28, 29]])
However, I’d like to know, is there a way to do this elegantly in numpy without making the 1-dimensional vector b into a matrix where all the rows repeat?
There is a way to do this in Pandas as solved in this question.
Answers:
Use a < 3
as mask and b
as fill_value
to get the initial array filled on masked values:
a = np.ma.array(a, mask=a < 3, fill_value=b).filled()
print(a)
[[ 0 0 0 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 3 22 23]
[ 4 25 26 27 28 29]]
Why not use np.where
?
>>> np.where(a < 3, b, a)
array([[ 0, 0, 0, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 3, 22, 23],
[ 4, 25, 26, 27, 28, 29]])
I’m interested in whether it’s possible do the following with pure numpy.
Let’s say I have a matrix a and a vector b. I want to fill whatever values meet the condition to the left of the equal sign with the value from the vector b correponding to the row in matrix a.
import numpy as np
a = np.arange(30).reshape(5,6)
a[3,3] = 2
a[4,0] = 1
a
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 2, 22, 23],
[ 1, 25, 26, 27, 28, 29]])
b = np.arange(0,5)[:,None]
b
array([[0],
[1],
[2],
[3],
[4]])
a[a<3] = b
TypeError: NumPy boolean array indexing assignment requires a 0 or 1-dimensional input, input has 2 dimensions
I understand why this doesn’t work and that I would need to reshape b to the same shape as a, and then subset it by a<3 first
b_mat = np.full(a.shape, b)
a[a<3] = b_mat[a<3]
a
array([[ 0, 0, 0, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 3, 22, 23],
[ 4, 25, 26, 27, 28, 29]])
However, I’d like to know, is there a way to do this elegantly in numpy without making the 1-dimensional vector b into a matrix where all the rows repeat?
There is a way to do this in Pandas as solved in this question.
Use a < 3
as mask and b
as fill_value
to get the initial array filled on masked values:
a = np.ma.array(a, mask=a < 3, fill_value=b).filled()
print(a)
[[ 0 0 0 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 3 22 23]
[ 4 25 26 27 28 29]]
Why not use np.where
?
>>> np.where(a < 3, b, a)
array([[ 0, 0, 0, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 3, 22, 23],
[ 4, 25, 26, 27, 28, 29]])