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.

Answer from unutbu on Stack Overflow
๐ŸŒ
NumPy
numpy.org โ€บ devdocs โ€บ user โ€บ basics.indexing.html
Indexing on ndarrays โ€” NumPy v2.6.dev0 Manual
The above is not true for advanced indexing. You may use slicing to set values in the array, but (unlike lists) you can never grow the array. The size of the value to be set in x[obj] = value must be (broadcastable to) the same shape as x[obj].
๐ŸŒ
Python Like You Mean It
pythonlikeyoumeanit.com โ€บ Module3_IntroducingNumpy โ€บ AccessingDataAlongMultipleDimensions.html
Accessing Data Along Multiple Dimensions in an Array โ€” Python Like You Mean It
NumPy specifies the row-axis (students) ... each axis (dimension), to uniquely specify an element in this 2D array; the first number specifies an index along axis-0, the second specifies an index along axis-1....
Discussions

numpy - Use 2d array as list of indices for n-D array - Stack Overflow
This is based on the idea that A[a,b] is the same as A[(a,b)]. And when a and b are matching lists or arrays, it selects values by pairing them up, roughly the same as ... For a product like indexing, the index arrays need to have more dimensions. More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - Indexing a 1D Numpy array using 2D array - Stack Overflow
Can you clarify exactly what you mean? The code you posted works correctly, and yes you can use a 2D array to index a 1D array. ... I couldn't find the rule in numpy documentation, can you point me to relevant documentation where this type of indexing is discussed. More on stackoverflow.com
๐ŸŒ stackoverflow.com
python - Index 2D numpy array by a 2D array of indices without loops - Stack Overflow
Appending [:, None] modifies the ... 2D array. The basic principle is that the number of dimensions in the index arrays must agree, and their shapes must also do so. See documentation for np.ix_ to get a feel for this. ... Find the answer to your question by asking. Ask question ... See similar questions with these tags. ... New site design and philosophy for Stack Overflow: Starting February 24, 2026... 0 Index a batch of numpy vectors with ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
Numpy indices-ifs for 2d array rows?
You do that exactly as you might expect. See: arr2d = np.array([[0,1,2],[3,4,5],[6,7,8]]) arr2d[np.sum(arr2d, axis=1) > 10] = 2 Here, np.sum(โ€ฆ, axis=1) sums across the column dimension โ€” row sums โ€” to give a 1D array of length (# of rows of arr2d). So np.sum(arr2d, axis=1) > 10 returns the 1D Boolean array [False, True, True] Finally, when you use that to index arr2D, Numpy implicitly copies entries across columns to match the second dimension of arr2D, giving the 2D mask [[ False, False, False] [ True, True, True] [ True, True, True]] which is exactly what you want. More on reddit.com
๐ŸŒ r/learnpython
4
2
August 16, 2021
Top answer
1 of 2
67
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.

2 of 2
4

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]])
๐ŸŒ
Python Like You Mean It
pythonlikeyoumeanit.com โ€บ Module3_IntroducingNumpy โ€บ AdvancedIndexing.html
Advanced Indexing โ€” Python Like You Mean It
This returns a copy of the data, as do all occurrences of advanced indexing. # advanced indexing returns a copy >>> np.shares_memory(y, y[index]) False ยท The indexing array can have an arbitrary shape; the resulting array will match that shape. # utilizing a 2D-array as an index >>> index_2d = np....
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ numpy-indexing
Numpy Array Indexing - GeeksforGeeks
December 17, 2025 - Here matrix[1, 2] accesses the element in the second row (index 1) and third column (index 2) which is 6. 3D Arrays: It can be visualized as a stack of 2D arrays, we need three indices- Depth: Specifies the 2D slice. Row: Specifies the row within the slice. Column: Specifies the column within the row. We can access elements by specifying row, column and depth indices like matrix[depth, row, column]. ... import numpy as np cube = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10, 11, 12], [13, 14, 15], [16, 17, 18]]]) print(cube[1, 2, 0])
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ indexing-multi-dimensional-arrays-in-python-using-numpy
Indexing Multi-dimensional arrays in Python using NumPy | GeeksforGeeks
April 28, 2025 - Python3 ยท import numpy as np arr_m = np.arange(12).reshape(2, 2, 3) print(arr_m) Output: [[[ 0 1 2] [ 3 4 5]] [[ 6 7 8] [ 9 10 11]]] To index a multi-dimensional array you can index with a slicing operation similar to a single dimension array.
Find elsewhere
๐ŸŒ
Programiz
programiz.com โ€บ python-programming โ€บ numpy โ€บ array-indexing
Numpy Array Indexing (With Examples)
In NumPy, we can access specific rows or columns of a 2-D array using array indexing. Let's see an example. import numpy as np # create a 2D array array1 = np.array([[1, 3, 5], [7, 9, 2], [4, 6, 8]]) # access the second row of the array second_row = array1[1, :] print("Second Row:", second_row) ...
Top answer
1 of 1
1

What array indexing rule applies to following code?

That's how numpy's advanced indexing works. The shape of result array is related to shape of index array, the array's shape and the axis you're passing the index. Here are some examples that passes a 3D array as index to the first axis of arrays with different shapes.

In [47]: a.shape
Out[47]: (2, 5)

In [48]: b = a[np.array([[[0],[1]],[[1],[1]]])]

In [49]: b.shape
Out[49]: (2, 2, 1, 5)

In [50]: arr.shape
Out[50]: (3, 3, 3)

In [51]: b = arr[np.array([[[0],[1]],[[1],[1]]])]

In [52]: b.shape
Out[52]: (2, 2, 1, 3, 3)

And here is what you get when you pass different arrays to different axises:

In [61]: b = arr[[[0],[2]],[[1],[0]]]

In [62]: b.shape
Out[62]: (2, 1, 3)

In [63]: arr.shape
Out[63]: (3, 3, 3)

In all of these indexings, Numpy will check multiple things, first off, it checks the type of the objects passed as index. Secondly, it compares the shapes of your index array with the shape of respective axis of your array. Thirdly, it checks if the result produces a valid Numpy array.

Here are some other examples:

In [64]: b = arr[[[[0],[2]]],[[1],[0]]]

In [65]: b.shape
Out[65]: (1, 2, 1, 3)

In [66]: b
Out[66]: 
array([[[[ 3,  4,  5]],

        [[18, 19, 20]]]])

In [67]: b = arr[[[[0],[2]]],[1],[0]]

In [68]: b
Out[68]: 
array([[[ 3],
        [21]]])

In [69]: b = arr[[[['a'],[2]]],[1],[0]]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-69-dba030ba9787> in <module>()
----> 1 b = arr[[[['a'],[2]]],[1],[0]]

IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

In [70]: b = arr[[[[0],[2]]],[1],0]

In [71]: b = arr[[[[0],[2]]],[5],0]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-71-0962012e570a> in <module>()
----> 1 b = arr[[[[0],[2]]],[5],0]

IndexError: index 5 is out of bounds for axis 1 with size 3

In [72]: 

In [72]: b = arr[[[[0],[[2]]]],[5],0]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-72-9a520b0cb30e> in <module>()
----> 1 b = arr[[[[0],[[2]]]],[5],0]

ValueError: setting an array element with a sequence.

In [73]: b = arr[[[[0],[[2]]]],[5],[0]]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-73-67187db6f452> in <module>()
----> 1 b = arr[[[[0],[[2]]]],[5],[0]]

ValueError: setting an array element with a sequence.
๐ŸŒ
NumPy
numpy.org โ€บ doc โ€บ stable โ€บ user โ€บ basics.indexing.html
Indexing on ndarrays โ€” NumPy v2.5 Manual
The above is not true for advanced indexing. You may use slicing to set values in the array, but (unlike lists) you can never grow the array. The size of the value to be set in x[obj] = value must be (broadcastable to) the same shape as x[obj].
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ python โ€บ numpy-index-3d-array-with-index-of-last-axis-stored-in-2d-array
Numpy: Index 3D array with index of last axis stored in 2D array - GeeksforGeeks
July 23, 2025 - This technique is particularly ... To index a 3D NumPy array using indices stored in a 2D array, we can use the numpy.take_along_axis function, which is designed for such tasks....
๐ŸŒ
Pluralsight
pluralsight.com โ€บ blog โ€บ tech guides & tutorials
Working with Numpy Arrays: Indexing & Slicing | Pluralsight
November 2, 2018 - That's because if the indices are missing, by default, Numpy inserts the starting and stopping indices that select the entire array. So writing array1[:] is equivalent to writing array1[0:9] You can extend this concept to include only the starting index. In this case, the slice includes all the elements from the starting index until the end of the array. For example: ... Or, alternatively, specify only the stopping index. ... As expected, the slice includes all the elements from the start of the array until the indexed value.
๐ŸŒ
W3Schools
w3schools.com โ€บ python โ€บ numpy โ€บ numpy_array_indexing.asp
NumPy Array Indexing
Think of 2-D arrays like a table with rows and columns, where the dimension represents the row and the index represents the column. Access the element on the first row, second column: import numpy as np arr = np.array([[1,2,3,4,5], [6,7,8,9,10]]) ...
๐ŸŒ
Mdjubayerhossain
mdjubayerhossain.com โ€บ numpy โ€บ notebooks โ€บ 04_ArraySlicingandSubsetting.html
Array Indexing and Slicing โ€” Introduction to NumPy
# Create a 2D array of students ... as many colons as needed to produce a complete indexing tuple ... NumPy arrays can be indexed with slices, but also with boolean or integer arrays (masks)....
๐ŸŒ
Uni-heidelberg
ita.uni-heidelberg.de โ€บ ~dullemond โ€บ lectures โ€บ python_2019 โ€บ py4sci_wed โ€บ Note on IndexOrdering.html
Index ordering in Numpy
Now things get really confusing! As you see, the index order is now: y,x,z, while the argument order to meshgrid() remains x,y,z. Therefore, for 3-D and higher-dimensional arrays, I recommend always to use indexing='ij'!
๐ŸŒ
Reddit
reddit.com โ€บ r/learnpython โ€บ numpy indices-ifs for 2d array rows?
r/learnpython on Reddit: Numpy indices-ifs for 2d array rows?
August 16, 2021 -

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

๐ŸŒ
Educative
educative.io โ€บ answers โ€บ how-does-array-indexing-work-using-numpy-in-python
How does array indexing work using NumPy in Python?
However, we specify a 2-D list because it is a two-dimensional array in this case. The first element in the list specifies the row indices. The second element specifies the column indices.
Top answer
1 of 4
16

You can use choose to make the selection:

>>> z_indices.choose(val_arr)
array([[ 9,  1, 20],
       [ 3,  4, 14],
       [24,  7, 17]])

The function choose is incredibly useful, but can be somewhat tricky to make sense of. Essentially, given an array (val_arr) we can make a series of choices (z_indices) from each n-dimensional slice along the first axis.

Also: any fancy indexing operation will create a new array rather than a view of the original data. It is not possible to index val_arr with z_indices without creating a brand new array.

2 of 4
7

With readability, np.choose definitely looks great.

If performance is of essence, you can calculate the linear indices and then use np.take or use a flattened version with .ravel() and extract those specific elements from val_arr. The implementation would look something like this -

def linidx_take(val_arr,z_indices):

    # Get number of columns and rows in values array
     _,nC,nR = val_arr.shape

     # Get linear indices and thus extract elements with np.take
    idx = nC*nR*z_indices + nR*np.arange(nR)[:,None] + np.arange(nC)
    return np.take(val_arr,idx) # Or val_arr.ravel()[idx]

Runtime tests and verify results -

Ogrid based solution from here is made into a generic version for these tests, like so :

In [182]: def ogrid_based(val_arr,z_indices):
     ...:   v_shp = val_arr.shape
     ...:   y,x = np.ogrid[0:v_shp[1], 0:v_shp[2]]
     ...:   return val_arr[z_indices, y, x]
     ...: 

Case #1: Smaller datasize

In [183]: val_arr = np.random.rand(30,30,30)
     ...: z_indices = np.random.randint(0,30,(30,30))
     ...: 

In [184]: np.allclose(z_indices.choose(val_arr),ogrid_based(val_arr,z_indices))
Out[184]: True

In [185]: np.allclose(z_indices.choose(val_arr),linidx_take(val_arr,z_indices))
Out[185]: True

In [187]: %timeit z_indices.choose(val_arr)
1000 loops, best of 3: 230 ยตs per loop

In [188]: %timeit ogrid_based(val_arr,z_indices)
10000 loops, best of 3: 54.1 ยตs per loop

In [189]: %timeit linidx_take(val_arr,z_indices)
10000 loops, best of 3: 30.3 ยตs per loop

Case #2: Bigger datasize

In [191]: val_arr = np.random.rand(300,300,300)
     ...: z_indices = np.random.randint(0,300,(300,300))
     ...: 

In [192]: z_indices.choose(val_arr) # Seems like there is some limitation here with bigger arrays.
Traceback (most recent call last):

  File "<ipython-input-192-10c3bb600361>", line 1, in <module>
    z_indices.choose(val_arr)

ValueError: Need between 2 and (32) array objects (inclusive).


In [194]: np.allclose(linidx_take(val_arr,z_indices),ogrid_based(val_arr,z_indices))
Out[194]: True

In [195]: %timeit ogrid_based(val_arr,z_indices)
100 loops, best of 3: 3.67 ms per loop

In [196]: %timeit linidx_take(val_arr,z_indices)
100 loops, best of 3: 2.04 ms per loop
๐ŸŒ
Towards Data Science
towardsdatascience.com โ€บ home โ€บ latest โ€บ introducing numpy, part 2: indexing arrays
Introducing NumPy, Part 2: Indexing Arrays | Towards Data Science
January 13, 2025 - Two-dimensional arrays are indexed with a pair of values. These value pairs resemble Cartesian coordinates, except that the row index (the axis-0 value) comes before the column index (the axis-1 value), as shown in the following figure.