快速numpy卷

dee*_*wal 5 python arrays performance numpy

我有一个2d numpy数组,我想以增量方式滚动每一行.我np.rollfor循环中使用这样做.但是因为我这几次打电话,我的代码真的很慢.你能帮我解决一下如何让它更快.

我的输入看起来像

array([[4,1],
       [0,2]])
Run Code Online (Sandbox Code Playgroud)

我的输出看起来像

array([[4,1],
       [2,0]])
Run Code Online (Sandbox Code Playgroud)

这里第0行[4,1]移动了0,第一行[0,2]移动了1.类似地,第二行将移动2,依此类推.

编辑

temp = np.zeros([dd,dd])
for i in range(min(t + 1, dd)):
    temp[i,:] = np.roll(y[i,:], i, axis=0)
Run Code Online (Sandbox Code Playgroud)

Div*_*kar 5

这是一个矢量化解决方案 -

m,n = a.shape
idx = np.mod((n-1)*np.arange(m)[:,None] + np.arange(n), n)
out = a[np.arange(m)[:,None], idx]
Run Code Online (Sandbox Code Playgroud)

样本输入,输出 -

In [256]: a
Out[256]: 
array([[73, 55, 79, 52, 15],
       [45, 11, 19, 93, 12],
       [78, 50, 30, 88, 53],
       [98, 13, 58, 34, 35]])

In [257]: out
Out[257]: 
array([[73, 55, 79, 52, 15],
       [12, 45, 11, 19, 93],
       [88, 53, 78, 50, 30],
       [58, 34, 35, 98, 13]])
Run Code Online (Sandbox Code Playgroud)

因为,您已经提到过多次调用这样的滚动例程,创建idx一次索引数组并稍后重新使用它.

进一步改进

对于重复使用,最好创建完整的线性索引,然后使用np.take提取滚动元素,如下所示 -

full_idx = idx + n*np.arange(m)[:,None]
out = np.take(a,full_idx)
Run Code Online (Sandbox Code Playgroud)

让我们看看改善之处是什么 -

In [330]: a = np.random.randint(11,99,(600,600))

In [331]: m,n = a.shape
     ...: idx = np.mod((n-1)*np.arange(m)[:,None] + np.arange(n), n)
     ...: 

In [332]: full_idx = idx + n*np.arange(m)[:,None]

In [333]: %timeit a[np.arange(m)[:,None], idx] # Approach #1
1000 loops, best of 3: 1.42 ms per loop

In [334]: %timeit np.take(a,full_idx)          # Improvement
1000 loops, best of 3: 486 µs per loop
Run Code Online (Sandbox Code Playgroud)

3x那里改善!