我有一个2d numpy数组,我想以增量方式滚动每一行。我在np.roll
循环中使用for
来执行此操作。但是因为我这几次打电话,我的代码真的很慢。你能帮我解决一下如何加快速度。
我的输入看起来像
array([[4,1],
[0,2]])
我的输出看起来像
array([[4,1],
[2,0]])
此处第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)
答案 0 :(得分: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]
示例输入,输出 -
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]])
因为,您已经提到过多次调用这样的滚动例程,所以创建一次索引数组idx
并稍后重新使用它。
进一步改善
对于重复使用,最好创建完整的线性索引,然后使用np.take
提取滚动元素,如下所示 -
full_idx = idx + n*np.arange(m)[:,None]
out = np.take(a,full_idx)
让我们看看改进之类的是什么 -
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
围绕 3x
进行改进!
答案 1 :(得分:1)
一个棘手但快速的解决方案:
p=5
a=randint(0,p,(p,p))
aa=hstack((a,a))
m,n=aa.strides
b=np.lib.stride_tricks.as_strided(aa,a.shape,(m+n,n))
c=np.lib.stride_tricks.as_strided(aa.ravel()[p:],a.shape,(m-n,n))
##
[[2 1 4 2 4]
[0 4 2 0 3]
[1 3 3 4 4]
[1 0 3 2 4]
[3 3 2 1 3]]
[[2 1 4 2 4]
[4 2 0 3 0]
[3 4 4 1 3]
[2 4 1 0 3]
[3 3 3 2 1]]
[[2 1 4 2 4]
[3 0 4 2 0]
[4 4 1 3 3]
[3 2 4 1 0]
[3 2 1 3 3]]