这是受thispost启发的。你知道吗
考虑一个函数f
,它返回用户通常用于索引其他数组的1d 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)
替换(它将用1填充整个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)
替换“X”,在另外两个示例中用slice(None)
替换。你知道吗
但这相当笨拙,更不用说增加的开销可能会消耗掉我们获得的任何速度。你知道吗
有更简单的策略吗?
虽然一个是副本,另一个是视图,但它们看起来是一样的:
但是如果第二个索引是一个数组,那么
arange
和slice
就不是替代品。你知道吗为了匹配切片版本,我必须向
arange
添加一个维度。你知道吗我不知道一个切片表达式会产生
Out[110]
。你知道吗因此,除了用
slice
替换arange
之外,我们还需要注意高级索引数组如何相互广播,以及切片意味着什么广播。你知道吗对于3维或更多维,混合切片和高级索引变得更加复杂,如https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing中所述
相关问题 更多 >
编程相关推荐