這是靈感來自this的帖子。numpy高級索引:透明地優化範圍?
考慮一個函數f
,該函數返回用戶通常用來索引其他數組的索引的第一個np.ndarray
idx
。進一步假定f
經常出現的結果是歸還全部法律索引。在鏈接的帖子中,建議這是由f
返回slice(None)
而不是np.arange(maxind)
。
由於高級索引是有代價的
>>> a = np.arange(1_000_000)
>>> direct = lambda: np.sum(a[:])
>>> indirect = lambda: np.sum(a[a])
>>> timeit(direct, number=100)
0.07656216900795698
>>> timeit(indirect, number=100)
0.2885982050211169
這看起來像是一見鍾情合理的優化。
不幸的是,它不是「正確的」。想象一下,例如,用戶想要創建idx
的單熱表示。要去這樣做的一個簡單的方法是
result = np.zeros((k, maxind), dtype=int)
result[np.arange(k), idx] = 1
這打破如果np.arange(maxind)
由slice(None)
取代(這將填補result
與那些整)。
所以我的問題是:一,可以有自己的蛋糕,在這裏吃,即:
有什麼f
可以返回忠實模仿的np.arange(maxind)
語義,同時避免可能的高級索引在哪裏?
由於我差點辭職,答案是沒有:
什麼是未來最好的事情?
也許會返回一個「增強np.s_
」,即一個工程__getitem__
?
class smart_idx:
def __init__(self, n):
self.n = n
def __getitem__(self, idx):
idx = idx if isinstance(idx, tuple) else (idx,)
if idx:
count = idx.count('X')
need_adv = count > 1
if count == 1:
for i in idx:
if not isinstance(i, slice) and i != Ellipsis:
need_adv = True
break
repl = np.arange(self.n) if need_adv else slice(None)
return tuple(repl if i == 'X' else i for i in idx)
return slice(None)
的用戶將不得不使用它像
data[idx[3, 4:9, 'X', [1,3,2,6]]]
data[idx['X', ..., :4:-1]]
data[idx[]]
和__getitem__
,檢測所述先進索引將決定在其他兩個實施例與第一np.arange(4)
並用slice(None)
替換「X」。
但是這相當笨拙,更不用說增加的開銷可能會吃掉我們獲得的任何速度。
是否有簡單的策略?
描述如果'idx'是一個列表/數組你是否要使用要得到高級索引,不管切片或arange爲其他索引。在'[arange ...,idx]'索引中,它從每一行中選取一個項目。在扁平數組上索引更快,但是通過計算扁平索引的成本來平衡。 – hpaulj
@hpaulj「如果idx是一個列表/數組,您將獲得高級索引,無論」。這就是爲什麼我們試圖在有意義的特殊情況下(基本上'idx == np.arange(maxind)'+沒有其他高級索引)用'slice(None)'替換'idx'。 –
@hpaulj試圖說的是,無論「idx」是什麼,當您爲> 1D(例如2D中的任意位置)編制索引時,例如, '[something ...,idx]'無論'idx'可能是什麼,它都是高級索引,除非'something'和'idx'都是'slice'對象,但這種情況永遠不會模仿你想要的行爲。 –