2017-02-07 14 views
5

Tôi có một mảng numpy 2d và tôi muốn cuộn từng hàng theo kiểu tăng dần. Tôi đang sử dụng np.roll trong vòng lặp for để thực hiện việc này. Nhưng kể từ khi tôi gọi nó hàng ngàn lần, mã của tôi rất chậm. Bạn có thể vui lòng giúp tôi làm thế nào để làm cho nó nhanh hơn.Cuộn numpy nhanh

đầu vào của tôi trông giống như

array([[4,1], 
     [0,2]]) 

và đầu ra của tôi trông giống như

array([[4,1], 
     [2,0]]) 

đây hàng 0 [4,1] được chuyển bằng 0, và hàng đầu tiên [0,2] được chuyển bằng 1. Tương tự thứ hai hàng sẽ được dịch chuyển bởi 2 và cứ tiếp tục như vậy.

EDIT

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

Bạn có thể thấy cách bạn * cuộn * bạn hàng? –

+0

Đây là một giải pháp khả thi: http://stackoverflow.com/questions/20360675/roll-rows-of-a-matrix-independently –

Trả lời

5

Dưới đây là một giải pháp vectorized -

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

mẫu đầu vào, đầu ra -

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]]) 

Kể từ khi, bạn đã nói rằng bạn đang kêu gọi một cán như vậy thường xuyên nhiều lần, tạo ra các chỉ mục arra y idx một lần và sử dụng lại sau này.

cải thiện hơn nữa

Đối với tập quán lặp đi lặp lại, bạn là tốt hơn hết tạo ra các chỉ số tuyến tính đầy đủ và sau đó sử dụng np.take để trích xuất các thành phần cán, như vậy -

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

Hãy xem sự cải thiện là những gì như -

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 

Khoảng 3x cải thiện ở đó!

1

một giải pháp phức tạp nhưng nhanh:

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]] 
+0

Sử dụng rất tốt các bước tiến! Thứ tự cán được lật mặc dù. – Divakar

+0

có. Tôi nhìn theo hướng khác, nhưng nó không đơn giản như vậy .... :(. –

+0

Xếp chồng lên phiên bản lật cột? – Divakar

Các vấn đề liên quan