Reputation: 8778
Say I have a function call f(m1)
where m1
is a numpy matrix. Now, I would like to call f
on a matrix which is almost identical to m1
:
m2 = m1.copy()
m2[ 2, 7 ] = 43 # or m2[ 2, 7 ] += 43
f(m2)
Is there an elegant f( ... )
one-liner to do that?
Upvotes: 1
Views: 2370
Reputation: 46530
For pedagogy's sake, here is a functional way to do it. np.where
actually does exactly what you want, but the tricky part is that it accepts a boolean condition, not an index:
f(np.where(condition, 43, m1))
which sends 43
to f
wherever condition
is met, elsewhere it just sends m1
, so this would likely be simpler if we knew your criteria for choosing the element to change. As such, the trickiest part is creating the boolean array, which is a bit wasteful anyway.
np.where(np.all(np.indices(m1.shape) == np.array([2, 7])[:, None, None], 0), 43, m1)
or equivalently:
np.where(np.all(np.rollaxis(np.indices(m1.shape),0,3) == np.array([2, 7]), -1), 43, m1)
I could have sworn there was an equivalent function that took an index instead of a mask, but unfortunately it seems the similar functions (np.put
, e.g.) that take indices modify the array in place, instead of returning a new one functionally. np.choose
would also work but has the same issues of creating a "choice" array (as opposed to a condition mask array).
In action:
In [66]: m1 = np.zeros((4, 9))
In [67]: np.where(np.all(np.indices(m1.shape) == np.array([2, 7])[:,None, None], 0), 43, m1)
Out[67]:
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 43., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
In [68]: np.where(np.all(np.rollaxis(np.indices(m1.shape),0,3) == np.array([2, 7]), -1), 43, m1)
Out[68]:
array([[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 43., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
Upvotes: 0
Reputation: 3699
In python, every assignment is a statement and not an expression so you cannot do -
f(m2[2,7] = 43)
or
if (a = 1+2)
I believe you can do
f( modify_matrix(m1) )
and define a separate method for modifying m1 matrix.
def modify_matrix(m1):
m1[2,7] = 2
return m1
But above options are more complex if all you need to do is just add one more line of modifying the matrix.
Upvotes: 1