Numpy ndarray: понимание среза объектов и ":" - PullRequest
0 голосов
/ 28 августа 2018

Предположим, у вас есть:

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

вызывающий

data[:, 1]

выходы

[1. 1.]

однако

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

выходы

[[1.]
 [1.]]

как получилось?

Как бы я явно написал объект среза, чтобы получить эквивалент [:, 1]?

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Индексирование с помощью объекта-фрагмента отличается от семантики индексации. Индексирование с одним целым числом сворачивает / удаляет соответствующее измерение, тогда как индексирование срезом никогда не делает этого.

Если вы хотите вести индексирование одним целым числом вдоль определенной оси, вы можете эмулировать его с помощью среза и некоторой логики изменения формы после этого; но наименее запутанным решением было бы просто заменить этот срез соответствующим целым числом.

В качестве альтернативы есть np.squeeze. Абсолютно никогда не используйте его без ключевого слова axis, поскольку это гарантированный рецепт кода, который вызывает непреднамеренное поведение. Но сжатие только тех осей, которые вы нарезали, будет иметь тот эффект, который вам нужен.

Если вы позволите мне мини-разглагольствовать: на более высоком уровне, я подозреваю, что то, что вы ищете, все же очень много антипаттерна. Если бы мне пришлось сформулировать первое правило numpy, это не сжимать оси только потому, что они оказываются одноэлементными. Примите ndarrays и поймите, что большее количество осей не делает ваш код более сложным, но позволяет вам выразить осмысленную семантику ваших данных. Тот факт, что вы нарезаете эту ось в первую очередь, говорит о том, что размер этой оси принципиально не равен 1; просто так бывает в конкретном случае. Сжатие этого одноэлементного измерения сделает практически невозможным, чтобы любой нисходящий код был написан в недоуменной и безошибочной манере. Если вам абсолютно необходимо сжать массив, как, скажем, перед передачей его в функцию plot, обработайте его так, как если бы переменная, размещенная в стеке, в C ++ и не позволяла ссылаться на него из текущей области видимости, потому что вы будете искажены семантика этого массива и нижестоящий код больше не знают, «на что он смотрит».

0 голосов
/ 28 августа 2018

Похоже, вам нужно самостоятельно удалить одноэлементные измерения после использования slice объекта. Или есть некоторые детали реализации, которые я не понимаю.

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())

Выход:

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