In [1]: import numpy as np
In [2]: a = np.array([[2,0],[3,0],[3,1],[5,0],[5,1],[5,2]])
In [3]: b = np.zeros((6,3), dtype='int32')
In [4]: b[a[:,0], a[:,1]] = 10
In [5]: b
Out[5]:
array([[ 0, 0, 0],
[ 0, 0, 0],
[10, 0, 0],
[10, 10, 0],
[ 0, 0, 0],
[10, 10, 10]])
Why it works:
If you index b with two numpy arrays in an assignment,
b[x, y] = z
then think of NumPy as moving simultaneously over each element of x and each element of y and each element of z (let's call them xval, yval and zval), and assigning to b[xval, yval] the value zval. When z is a constant, "moving over z just returns the same value each time.
That's what we want, with x being the first column of a and y being the second column of a. Thus, choose x = a[:, 0], and y = a[:, 1].
b[a[:,0], a[:,1]] = 10
Why b[a] = 10 does not work
When you write b[a], think of NumPy as creating a new array by moving over each element of a, (let's call each one idx) and placing in the new array the value of b[idx] at the location of idx in a.
idx is a value in a. So it is an int32. b is of shape (6,3), so b[idx] is a row of b of shape (3,). For example, when idx is
In [37]: a[1,1]
Out[37]: 0
b[a[1,1]] is
In [38]: b[a[1,1]]
Out[38]: array([0, 0, 0])
So
In [33]: b[a].shape
Out[33]: (6, 2, 3)
So let's repeat: NumPy is creating a new array by moving over each element of a and placing in the new array the value of b[idx] at the location of idx in a. As idx moves over a, an array of shape (6,2) would be created. But since b[idx] is itself of shape (3,), at each location in the (6,2)-shaped array, a (3,)-shaped value is being placed. The result is an array of shape (6,2,3).
Now, when you make an assignment like
b[a] = 10
a temporary array of shape (6,2,3) with values b[a] is created, then the assignment is performed. Since 10 is a constant, this assignment places the value 10 at each location in the (6,2,3)-shaped array.
Then the values from the temporary array are reassigned back to b.
See reference to docs. Thus the values in the (6,2,3)-shaped array are copied back to the (6,3)-shaped b array. Values overwrite each other. But the main point is you do not obtain the assignments you desire.
Is it possible to access multidimensional numpy array with a single index without a reshape?
Numpy indices-ifs for 2d array rows?
using np.where on a 2D array
Python optimization
In [1]: import numpy as np
In [2]: a = np.array([[2,0],[3,0],[3,1],[5,0],[5,1],[5,2]])
In [3]: b = np.zeros((6,3), dtype='int32')
In [4]: b[a[:,0], a[:,1]] = 10
In [5]: b
Out[5]:
array([[ 0, 0, 0],
[ 0, 0, 0],
[10, 0, 0],
[10, 10, 0],
[ 0, 0, 0],
[10, 10, 10]])
Why it works:
If you index b with two numpy arrays in an assignment,
b[x, y] = z
then think of NumPy as moving simultaneously over each element of x and each element of y and each element of z (let's call them xval, yval and zval), and assigning to b[xval, yval] the value zval. When z is a constant, "moving over z just returns the same value each time.
That's what we want, with x being the first column of a and y being the second column of a. Thus, choose x = a[:, 0], and y = a[:, 1].
b[a[:,0], a[:,1]] = 10
Why b[a] = 10 does not work
When you write b[a], think of NumPy as creating a new array by moving over each element of a, (let's call each one idx) and placing in the new array the value of b[idx] at the location of idx in a.
idx is a value in a. So it is an int32. b is of shape (6,3), so b[idx] is a row of b of shape (3,). For example, when idx is
In [37]: a[1,1]
Out[37]: 0
b[a[1,1]] is
In [38]: b[a[1,1]]
Out[38]: array([0, 0, 0])
So
In [33]: b[a].shape
Out[33]: (6, 2, 3)
So let's repeat: NumPy is creating a new array by moving over each element of a and placing in the new array the value of b[idx] at the location of idx in a. As idx moves over a, an array of shape (6,2) would be created. But since b[idx] is itself of shape (3,), at each location in the (6,2)-shaped array, a (3,)-shaped value is being placed. The result is an array of shape (6,2,3).
Now, when you make an assignment like
b[a] = 10
a temporary array of shape (6,2,3) with values b[a] is created, then the assignment is performed. Since 10 is a constant, this assignment places the value 10 at each location in the (6,2,3)-shaped array.
Then the values from the temporary array are reassigned back to b.
See reference to docs. Thus the values in the (6,2,3)-shaped array are copied back to the (6,3)-shaped b array. Values overwrite each other. But the main point is you do not obtain the assignments you desire.
TL;DR: Use advanced indexing: b[*a.T] = 10
You can also transpose the index array a, convert the result into a tuple and index the array b and assign a value. Converting the index array into a tuple (or unpacking it inside a []) ensures that multidimensional indexing works as expected. This is assignment by advanced indexing.
a = np.array([[2, 0], [3, 0], [3, 1], [5, 0], [5, 1], [5, 2]])
b = np.zeros((6,3), dtype ='int32')
b[*a.T] = 10
# or
b[tuple(a.T)] = 10
# or
b[(*a.T,)] = 10
# or
b[(*a.T.tolist(),)] = 10
All of them produce the expected output of
array([[ 0, 0, 0],
[ 0, 0, 0],
[10, 0, 0],
[10, 10, 0],
[ 0, 0, 0],
[10, 10, 10]])
[SOLVED]
I have this piece of code
import numpy as np arr = np.array([[1, 2], [4, 5], [7, 8]]) # arr.reshape(6) print(arr[0])
which returns [1 2] as expected (please, note, that arr.reshape(6) is commented).
But is there a property or a trick to access the elements with one index without using a reshape? So I could pass argument 0 and get 1 returned:0 -> 11 -> 22 -> 43 -> 5...
hello,
there is a feature in numpy that lets you find array elements with certain properties, for example:
import numpy as np arr = np.array([5,6,2,6,7,9,2,1,4,7,0,6]) print(arr[arr>5]) => [6, 6, 7, 9, 7, 6] # this works great for quick substitutions: arr2 = np.array([9,9,9,9,9,9,9,9,9,9,9,9]) arr[arr<5] = arr2[arr<5] print(arr) => [5, 6, 9, 6, 7, 9, 9, 9, 9, 7, 9, 6] # it even keeps dimensions: arr2d = np.array([[0,1,2],[3,4,5],[6,7,8]]) arr2d[arr2d<4] = 99 print(arr2d) =>[[99 99 99] [99 4 5] [ 6 7 8]]
Now to my question:
The 'if thingies' loop through every element of an array regardless of it's dimensions, creates a 1d bool array, which is then fed into the square brackets and then the operation is only performed if the bool at the current index is true.
Is there any way that this 'if' does not look at each individual element, but for example at a whole row? Can you specify how "deep" the search should be?
# task (not a real task, just demonstration): replace all rows that have a sum > 10 with a row containing only twos # replace? yes yes no yes no arr = np.array([[2,3,7], [9,1,1], [3,4,1], [4, 4, 4], [0, 7, 1]]) # this search now should only penetrate the first layer of the 2d array and not the second one, so i dont get individual numbers in my comparison/selection, but whole "rows/subarrays" arr[*black magic*] = (2, 2, 2) print(arr) => [[2,2,2], [2,2,2], [3,4,1], [2, 2, 2], [0, 7, 1]]
Thank you for your help!
I know this is very confusing and probably even more confusing if the person reading this is not me, so please tell me if what i wrote is utter nonsense
i know that you can do it with for loops or list comprehension, but i want to know if this specific form works, because i think it's a very cool feature