简体   繁体   中英

Numpy ndarray: understanding slice objects and “:”

Suppose you have:

data = np.array([ 
        [ 0,   1   ],
        [ 0,   1   ] 
      ], dtype='int64')

calling

data[:, 1]

yields

[1. 1.]

however

data[(slice(None,None,None), slice(1,2,None))]

yields

[[1.]
 [1.]]

how come?

How would I explicitly write the slice object to get the equivalent of [:, 1] ?

Indexing with a slice object has different semantics from indexing with an integer. Indexing with a single integer collapses / removes the corresponding dimension, whereas indexing with a slice never does so.

If you want to have the behavior of indexing with a single integer along a certain axis, you could emulate it with a slice and some reshaping logic after that; but the least convoluted solution would be to just replace that slice with the corresponding integer.

Alternatively, there is np.squeeze. Absolutely never use it without the axis keyword since that is an guaranteed recipe for code that produces unintentional behavior. But squeezing only those axes that you sliced will have the effect that you seem to be after.

If you will permit me a mini-rant: On a higher level, I suspect that what you are after is very much a numpy-antipattern though. If I had to formulate the first rule of numpy, it is not squeeze axes just because they happen to be singleton. Embrace ndarrays and realize that more axes does not make your code more complicated, but it allows you to express meaningfull semantics of your data. The fact that you are slicing this axis in the first place suggests that the size of this axis isnt fundamentally 1; it just happens to be so in a particular case. Squeezing out that singleton dimension is going to make it near impossible for any downstream code to be written in a numpythonic and bugfree manner. If you absolutely must squeeze an array, like say before passing it to a plot function, treat it like you would a stack allocated variable in C++ and don't let any reference to it leak out of the current scope, because you will have garbled the semantics of that array, and downstream code no longer knows 'what is it looking at'.

Seems like you need to remove singleton dimensions yourself after using a slice object. Or there is some underlying implementation detail that I don't understand.

import numpy as np
data = np.array([
        [ 0,   1   ],
        [ 0,   1   ]
      ], dtype='int64')
print("desired result")
print(data[:, 1])
print("first try")
print(data[(slice(None,None,None), slice(1,2,None))])
print("solution")
print(data[[slice(None,None,None), slice(1,2,None)]].squeeze())

output:

desired result
[1 1]
first try
[[1]
 [1]]
solution
[1 1]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM