2014-01-18 2 views
2

나는 두 개의 numpy 배열 x와 y를 가지고있다. 예 :둘 이상의 얼간이 배열의 롤링 창에서 동시에 반복하는 더 빠른 방법?

x 
Out[1]: 
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 
     17, 18, 19]) 
y 
Out[1]: 
array([100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 
     113, 114, 115, 116, 117, 118, 119]) 

x와 y에 대해 n주기 롤 오버 윈도우를 동시에 반복하고 싶습니다.

롤링 윈도우를 수십 개의 배열로 유지하면서 최대한 빨리이 작업을 수행하고 싶습니다. 나는 뻔뻔하게 itertools 문서에서 몇 가지 코드를 훔쳤다. 그리고 나서 np.array에서만 작동하는 자체 버전을 만들었습니다. 그러나 여기있는 사람이 내 기능을 더 빠르게 할 수 있는지 궁금해합니다.

내 소스 코드는 다음과 같습니다

from itertools import islice 
import numpy as np 

import time 
class Timer(object): 

    def __init__(self): 
     pass 

    def __enter__(self): 
     self.start = time.time() 
     return self   

    def __exit__(self,a,b,c): 
     print('ending') 
     self.end = time.time() 
     self.timetaken = self.end-self.start 
     print('Took {0} seconds'.format(self.timetaken)) 

def window(seq, n=2): 
    "Returns a sliding window (of width n) over data from the iterable" 
    " s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...     " 
    it  = iter(seq) 
    result = list(islice(it, n)) 
    if len(result) == n: 
     yield np.array(result).T  
    for elem in it: 
     result = result[1:] + [elem,]   
     yield np.array(result).T 

def npwindow(seq, n=2): 
    Zt  = Z.T  
    r = Zt[:n]  
    for zt in Zt[n:]: 
     r = np.roll(r, shift=-1, axis=0) 
     r[-1] = zt 
     yield r.T 


n = 100 
N = 1000 

x  = np.arange(N) 
y  = np.arange(100,N+100) 

Z  = np.array([x,y]) 

def npwindow_test(Z,n): 
    window2 = npwindow(Z,n) 
    for w in window2:  
     pass 
     #print('npwindow: {0}'.format(w)) 

def window_test(Z, n): 
    window1 = window(zip(*Z),n) 
    for w in window1: 
     pass 
     #print('window: {0}'.format(w)) 

num_iter = 10 
with Timer() as t0: 
    for i in range(num_iter): 
     npwindow_test(Z, n) 

with Timer() as t1: 
    for i in range(num_iter): 
     window_test(Z, n) 

print(' ratio : {0}'.format(t0.timetaken/t1.timetaken)) 

답변

3

롤링 창 np.lib.stride_tricks.as_strided()

참조 링크하여 수행 할 수 있습니다 : 그럼 당신이 할 수있는

import numpy as np 

n = 10 
N = 20 

x  = np.arange(N) 
y  = np.arange(100,N+100) 

Z  = np.vstack((x, y)) 

def rolling_window(a, window): 
    shape = a.shape[:-1] + (a.shape[-1] - window + 1, window) 
    strides = a.strides + (a.strides[-1],) 
    return np.lib.stride_tricks.as_strided(a, shape=shape, strides=strides) 


rZ = rolling_window(Z, n) 

: 여기

http://www.rigtorp.se/2011/01/01/rolling-statistics-numpy.html 코드입니다 rZ으로 계산하십시오. for 루프없이. 당신이 루프에 필요한 경우, 축 1 루프를 수행

for i in xrange(rZ.shape[1]): 
    print rZ[:, i, :] 

출력 :

[[ 0 1 2 3 4 5 6 7 8 9] 
[100 101 102 103 104 105 106 107 108 109]] 
[[ 1 2 3 4 5 6 7 8 9 10] 
[101 102 103 104 105 106 107 108 109 110]] 
[[ 2 3 4 5 6 7 8 9 10 11] 
[102 103 104 105 106 107 108 109 110 111]] 
[[ 3 4 5 6 7 8 9 10 11 12] 
[103 104 105 106 107 108 109 110 111 112]] 
[[ 4 5 6 7 8 9 10 11 12 13] 
[104 105 106 107 108 109 110 111 112 113]] 
[[ 5 6 7 8 9 10 11 12 13 14] 
[105 106 107 108 109 110 111 112 113 114]] 
[[ 6 7 8 9 10 11 12 13 14 15] 
[106 107 108 109 110 111 112 113 114 115]] 
[[ 7 8 9 10 11 12 13 14 15 16] 
[107 108 109 110 111 112 113 114 115 116]] 
[[ 8 9 10 11 12 13 14 15 16 17] 
[108 109 110 111 112 113 114 115 116 117]] 
[[ 9 10 11 12 13 14 15 16 17 18] 
[109 110 111 112 113 114 115 116 117 118]] 
[[ 10 11 12 13 14 15 16 17 18 19] 
[110 111 112 113 114 115 116 117 118 119]] 
+0

매우 인상적! 내 버전보다 대략 5 배 빠릅니다! – Ginger