I want to update an np.array
based on some indices.
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.array([1,2])
a[b, :][:, b] += 1
Afterwards, a
is unchanged, since just a copy got modified.
How can I modify the original object?
I want to update an np.array
based on some indices.
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.array([1,2])
a[b, :][:, b] += 1
Afterwards, a
is unchanged, since just a copy got modified.
How can I modify the original object?
Create an open mesh grid with numpy.ix_ and use it for the index. Using ix_
takes advantage of broadcasting, it saves space because it doesn't need to create the full complement of indices.
>>> import numpy as np
>>> np.ix_(b,b)
(array([[1],
[2]]), array([[1, 2]]))
>>>
>>> a[np.ix_(b,b)] += 10
>>> a
array([[ 0, 1, 2],
[ 3, 14, 15],
[ 6, 17, 18]])
>>>
Using ix_
is preferable for this use case but numpy.meshgrid could also be used. It has the disadvantage of creating a larger set of indices.
>>> np.meshgrid(b,b)
[array([[1, 2],
[1, 2]]), array([[1, 1],
[2, 2]])]
>>> a[np.meshgrid(b,b)] *= -1
>>> a
array([[ 0, 1, 2],
[ 3, -14, -15],
[ 6, -17, -18]])
>>>
Numpy's meshgrid is more typically used as descibed in What is purpose of meshgrid in Python? and Meshgrids and disambiguating rows and columns from Cartesian coordinates
First select rows using array b
and restrict the columns from position 1 to extract the square on the lower right corner.
>>> a
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# select the square on the lower right corner and increment it
>>> a[b, 1:] += 1
>>> a
array([[ 1, 2, 3],
[ 4, 6, 7],
[ 7, 9, 10]])
Alternatively, you can also use this:
>>> a[b, b[0]:] += 1
>>> a
array([[ 1, 2, 3],
[ 4, 6, 7],
[ 7, 9, 10]])
You need to do the indexing in one step. For what you're trying to do, this will work:
a[b[:, np.newaxis], b] += 1
print(a)
# array([[ 1, 2, 3],
# [ 4, 6, 7],
# [ 7, 9, 10]])
When you index an array with multiple lists of indices, those lists are broadcast together to index into the array. So if you have a 2x1 index and a 1x2 index, the resulting array slice is 2x2, and in this case references the 2x2 section of the array you were hoping to modify.