Home > Software engineering >  how to change element of matrix by a list of index
how to change element of matrix by a list of index

Time:12-05

how to change element of array according to a list of index Suppose I have

z = np.zeros([3, 3])
i = [[1, 1], [2, 0], [0, 2]]

where each element in i is an index of z, and i would like to change the corresponding element in z to be 1 obtain:

[[0, 0, 1], [0, 1, 0], [1, 0, 0]]

and i cannot use loop, since i actually have a much larger matrix than z. I try to use np.put, but it return

[[1, 1, 1], [0, 0, 0], [0, 0, 0]]

CodePudding user response:

Numpy's indexing means you can select multiple elements if you group the row coordinates and the column coordinates (or however many axes you may have) separately. Basically you want [[1, 2, 0], [1, 0, 2]], which is the transpose of your list of lists.

z[tuple(zip(*i))] = 1

CodePudding user response:

For multidimensional indexing, you have to use a tuple now. Any other sequence format is being deprecated, so:

z[tuple(zip(*i))] = 1
print(z)

Output:

[[0. 0. 1.]
 [0. 1. 0.]
 [1. 0. 0.]]

CodePudding user response:

You might want to set up your coordinates as an array rather than a list.

z = np.zeros([3, 3])
i = np.array([[1, 1], [2, 0], [0, 2]])

z[tuple(i.T)] = 1

print(z)

Output :

[[0. 0. 1.]
 [0. 1. 0.]
 [1. 0. 0.]]

CodePudding user response:

It depends a lot on data type of i.

If you're able to store i as array, it's better to use np.transpose instead of zip:

z = np.zeros([3, 3])
i = np.array([[1, 1], [2, 0], [0, 2]])
x, y = np.transpose(i)
z[x, y] = 1

It will change its view and that's costless. You need to unpack only two arguments x and y which is near costless too.

In comparison, zip creates a generator for Python - style iteration of every item in i which is more expensive:

z = np.zeros([3, 3])
i = [[1, 1], [2, 0], [0, 2]]
x, y = z[tuple(zip(*i))] = 1
z[x, y] = 1

The worst thing you can do is to call zip on numpy array because they are not designed for fast iteration.

There are some test that demonstrates advantages and disadvantages of zip vs np.transpose :

z = np.zeros([3000, 3000])
ii = np.random.randint(3000, size=(1500000, 2))
i = ii.tolist()

%%timeit
x, y = np.transpose(i) #lots of time spent for conversion into arr
z[x, y] = 1
3.07 s ± 32.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
x, y = np.transpose(ii)
z[x, y] = 1
106 ms ± 1.47 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
z[tuple(zip(*i))] = 1
1.26 s ± 14.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
  • Related