【发布时间】:2015-08-04 15:27:11
【问题描述】:
这个问题在底部有自己的答案。使用预先分配的数组。
多年前this question 的后续行动,numpy 中是否有规范的“移位”功能?我没有看到来自 the documentation 的任何内容。
这是我正在寻找的简单版本:
def shift(xs, n):
if n >= 0:
return np.r_[np.full(n, np.nan), xs[:-n]]
else:
return np.r_[xs[-n:], np.full(-n, np.nan)]
使用这个就像:
In [76]: xs
Out[76]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
In [77]: shift(xs, 3)
Out[77]: array([ nan, nan, nan, 0., 1., 2., 3., 4., 5., 6.])
In [78]: shift(xs, -3)
Out[78]: array([ 3., 4., 5., 6., 7., 8., 9., nan, nan, nan])
这个问题来自我昨天尝试write a fast rolling_product。我需要一种方法来“转移”累积产品,而我所能想到的就是复制 np.roll() 中的逻辑。
所以np.concatenate() 比np.r_[] 快得多。这个版本的函数性能要好很多:
def shift(xs, n):
if n >= 0:
return np.concatenate((np.full(n, np.nan), xs[:-n]))
else:
return np.concatenate((xs[-n:], np.full(-n, np.nan)))
更快的版本只是预先分配数组:
def shift(xs, n):
e = np.empty_like(xs)
if n >= 0:
e[:n] = np.nan
e[n:] = xs[:-n]
else:
e[n:] = np.nan
e[:n] = xs[-n:]
return e
上面的建议就是答案。使用预先分配的数组。
【问题讨论】:
-
想知道
np.r_[np.full(n, np.nan), xs[:-n]]是否可以替换为np.r_[[np.nan]*n, xs[:-n]],同样适用于其他条件,而不需要np.full -
@JohnGalt
[np.nan]*n是普通的 python,因此会比np.full(n, np.nan)慢。不适用于小n,但它会被 np.r_ 转换为 numpy 数组,这会带走优势。 -
@swenzel 刚刚计时,
[np.nan]*n比np.full(n, np.nan)快于n=[10,1000,10000]。需要检查np.r_是否被击中。 -
如果关注速度,数组大小对于最佳算法起着重要作用(在下面添加了基准比较)。此外,现在可以使用 numba.njit 来加快转换速度,如果重复调用的话。