2012-08-23 2 views
2

나 작은 예에 의해 그것을 설명하자Numpy : 모든 행이 왼쪽/오른쪽 컨텍스트로 스택되도록 행렬을 재 배열하는 가장 효율적인 방법은 무엇입니까?

>>> x = np.array([[1,2], [3,4], [5,6], [7,8]]) 
>>> x 
array([[1, 2], 
     [3, 4], 
     [5, 6], 
     [7, 8]]) 

내가 형태

다음
array([[0, 0, 1, 2, 3, 4], 
     [1, 2, 3, 4, 5, 6], 
     [3, 4, 5, 6, 7, 8], 
     [5, 6, 7, 8, 0, 0]]) 

을 가진 새로운 배열을 갖고 싶어, 컨텍스트의 크기를 +/- 1을 가지고,하지만 난 변수를 그대로 유지하고 싶습니다.

내가 지금까지하고 있어요 원래의 배열에 0을 추가한다 :

>>> y = np.concatenate((np.zeros((1, 2)), x, np.zeros((1, 2))), axis=0) 
>>> y 
array([[ 0., 0.], 
     [ 1., 2.], 
     [ 3., 4.], 
     [ 5., 6.], 
     [ 7., 8.], 
     [ 0., 0.]]) 

그리고 새로운 크기의 읽기 행하여 새 배열에 값을 넣어 :

>>> z = np.empty((x.shape[0], x.shape[1]*3)) 
>>> for i in range(x.shape[0]): z[i] = y[i:i+3].flatten() 

그 일의 종류, 그러나 나는 그것을 느리고, 못생긴 및 unpythonic 찾아 낸다. 이 재배치를 수행하는 더 좋은 방법을 생각해 볼 수 있습니까? 인플레 이스 틱 솔루션 : 추가 엄지 손가락은

답변

2

stride_tricks를 사용하는 옵션이 있습니다, 그러나 나는 말을하지 않습니다 이것이 "가장 효율적인 방법"이지만 가독성을 고려할 때 항상 최선이되는 것은 아니며 화재로 노는 것입니다. z 여기 당신이 그들 중 하나를 편집하는 경우, 그렇지 않으면 당신의 예에서 모두 1이 변경됩니다 만보기, 그래서 그것을 편집하기 전에 예상하지 못한 일을 방지하기 위해 z.copy()를 사용하는 것이

# We make it flat (and copy if necessary) to be on the safe side, and because 
# it is more obvious this way with stride tricks (or my function below): 
y = y.ravel() 

# the new shape is (y.shape[0]//2-2, 6). When looking at the raveled y, the first 
# dimension takes steps of 2 elements (so y.strides[0]*2) and the second is 
# just the old one: 
z = np.lib.stride_tricks.as_strided(y, shape=(y.shape[0]//2-2, 6), 
             strides=(y.strides[0]*2, y.strides[0])) 

참고. 위쪽에서 "현재 위치"로 이것을 의미하는 경우 y의 요소를 변경할 수 있으며 z도 변경됩니다.

# 6 values long window, but only every 2nd step on the original array: 
z = rolling_window(y, 6, asteps=2) 

중요 : 자체np.lib.stride_tricks.as_strided하지 일반적으로 안전입니다

당신과 마지막 줄을 대체 https://gist.github.com/3430219에서 내 rolling_window 기능을 체크 아웃 어쩌면,이 마법의 더 많은 일을하려는 경우 분할 결함을 만들 수 있으므로주의해서 사용해야합니다.

+0

대단히 고마워요! 빠른 지옥과 메모리 효율적인. 여기서 약간의 가독성을 감당할 수 있으므로 귀하의 대답을 고수 할 것입니다. – Pavel

1

인덱싱 작업을해야합니다 :

y = np.concatenate(([0, 0], x.flat, [0, 0])) # or use np.pad with NumPy 1.7 
i = np.tile(np.arange(6), (4, 1)) + np.arange(4)[:, None] * 2 
z = y[i] 

을 원하는 경우 분명히이 올바른 위치입니다! 이 유연한 만들기

array([[ 0, 1, 2, 3, 4, 5], 
     [ 2, 3, 4, 5, 6, 7], 
     [ 4, 5, 6, 7, 8, 9], 
     [ 6, 7, 8, 9, 10, 11]]) 

:

i 인덱싱 배열을 살펴보고, 이것이 어떻게 작동하는지 확인하려면

context = 1 
h, w = x.shape 
zeros = np.zeros((context, w), dtype=x.dtype) 
y = np.concatenate((zeros, x, zeros), axis=0).flat 
i = np.tile(np.arange(w + 2 * context * w), (h, 1)) + np.arange(h)[:, None] * w 
z = y[i] 
+0

고마워, ecatmur, 이건 좀 이상 해 보이지만 'strides'만큼 빠르지는 않아. – Pavel

관련 문제