Search code examples
numpymatrix-indexing

numpy - is Z[[1, 2],[1]] completely same with Z[(1,2),(1)]?


As per the answer of numpy - why Z[(0,2)] is view but Z[(0, 2), (0)] is copy?, now understood comma can trigger advanced indexing which is also warned in the document.

Warning The definition of advanced indexing means that x[(1,2,3),] is fundamentally different than x[(1,2,3)]. The latter is equivalent to x[1,2,3] which will trigger basic selection while the former will trigger advanced indexing. Be sure to understand why this occurs.

Once advance indexing is triggered with comma, is tuple indexing the same with array indexing? If so, why there are two ways to do the same?

If they are not, please help understand why and the rational/decision behind to decipher the numpy behaviors.

Z = np.arange(12).reshape(3, 4)
print("Z is \n{}\n".format(Z))

print("Z[[1, 2],[1]] is \n{} Is view {}\n__array_interface__ {}\n".format(
    Z[
        [1,2],
        [1]
    ],
    Z[[1,2],[1]].base is not None,
    Z[[1,2],[1]].__array_interface__
))

# Comparison with tuple indexing
print("Z[(1,2),(1)] is \n{} Is view {}\n__array_interface__ {}\n".format(
    Z[
        (1,2),
        (1)
    ],
    Z[(1,2),(1)].base is not None,
    Z[(1,2),(1)].__array_interface__
))
---
Z is 
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

Z[[1, 2],[1]] is 
[5 9] Is view False
__array_interface__ {'data': (94194177532720, False), 'strides': None, 'descr': [('', '<i8')], 'typestr': '<i8', 'shape': (2,), 'version': 3}

Z[(1,2),(1)] is 
[5 9] Is view False
__array_interface__ {'data': (94194177118656, False), 'strides': None, 'descr': [('', '<i8')], 'typestr': '<i8', 'shape': (2,), 'version': 3}

Solution

  • Z[[1, 2],[1]]
    

    Indexes the first dimension with a list [1,2], and the second with list [1]. Actually indexes with np.array([1,2]) broadcasted against np.array([1]). So it's the 2 elements from rows 1 and 2, and column 1.

    Z[(1,2),(1)]
    

    is the same. Both have a comma creating an outer tuple which is passed to the __getitem__ method. np.array((1,2)) is the same as np.array([1,2]). (1) is not a tuple, it's just 1 (no comma). Again, rows 1 and 2, column 1.

    Z[(x,y)] is the same as Z[x,y]; it's the comma that makes the tuple, not the ().

    x[(1,2,3),]
    

    The comma creates a tuple ((1,2,3),), and in effect tells x.__getitem__ that we are selecting from the first dimension of x. x[[1,2,3],] and x[np.array([1,2,3]),] are the same.

    x[(1,2,3)]
    

    is equivalent to x[1,2,3], providing scalar indices for 3 dimensions of x.