[SOLVED] Why does NumPy advanced indexing yield different results for list of lists and numpy array?

Issue

I have a question about NumPy’s advanced indexing.

I found this question, but I guess my question is slightly different.

In the example below x_array is the expected result. But when I tried the same with a list the result is different.

From the numpy doc:

Advanced indexing is triggered when the selection object, obj, is a
non-tuple sequence object, an ndarray (of data type integer or bool),
or a tuple with at least one sequence object or ndarray (of data type
integer or bool). There are two types of advanced indexing: integer
and Boolean.

import numpy as np

vertices = np.arange(9).reshape((3,3))

idx_list = [[0, 1, 2],
            [0, 2, 1]]

x_list = vertices[idx_list]

print('list')

print(x_list)

#this works as expected
idx_array = np.array(idx_list)
x_array = vertices[idx_array]

print('array')
print(x_array)

idx_list should trigger advanced indexing as it is a “non-tuple sequence object?” Or is a list and a tuple the same here and it is “a tuple with at least one sequence object”

Using the list yields the same as when passing the two list entries separated by a comma within the square brackets (one for each dimension).

x_list_2 = vertices[idx_list[0], idx_list[1]] 

This is also the behaviour I expect.

Solution

In the end it comes down to what is mentioned in https://stackoverflow.com/a/40599589/7919597

From numpy’s indexing documentation:

In order to remain backward compatible with a common usage in Numeric,
basic slicing is also initiated if the selection object is any
non-ndarray sequence (such as a list) containing slice objects, the
Ellipsis object, or the newaxis object, but not for integer arrays or
other embedded sequences.

The example with the list triggers an undocumented part of the backward compatibility logic, as described in a comment in the source code:

/*
 * Sequences < NPY_MAXDIMS with any slice objects
 * or newaxis, Ellipsis or other arrays or sequences
 * embedded, are considered equivalent to an indexing
 * tuple. (`a[[[1,2], [3,4]]] == a[[1,2], [3,4]]`)
 */

Answered By – Joe

Answer Checked By – Katrina (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *