2013-08-21 5 views
7

의 3D 배열의 2D 슬라이스의 의미하기 나는의 모양과 NumPy와 배열이 : 나는 배열의 각 '조각'의 25 개 요소를 통해 평균을 계산하려는NumPy와

(11L, 5L, 5L) 

을 [ 0, :, :], [1, :, :] 등 11 개의 값을 반환합니다.

어리석은 것처럼 보이지만이를 수행하는 방법을 찾을 수 없습니다. 나는 mean(axis=x) 함수가 이것을 할 것이라고 생각했지만 축의 모든 가능한 조합을 시도했지만 그 중 아무 것도 내가 원하는 결과를주지 못했습니다.

분명히 for 루프와 슬라이싱을 사용하여이 작업을 수행 할 수 있지만 더 좋은 방법이 있을까요?

답변

11

이 튜플을 사용하여 축 :

>>> a = np.arange(11*5*5).reshape(11,5,5) 
>>> a.mean(axis=(1,2)) 
array([ 12., 37., 62., 87., 112., 137., 162., 187., 212., 
     237., 262.]) 

편집 :이 wor numpy 버전 1.7 이상에서만 ks.

+2

그것은 작동합니까? 하나는 1.7 이후에 그렇게 생각할 것이지만, 문서는 여전히 하나의 축만을 말합니다. – Jaime

+1

numpy 버전에 대해서는 생각하지 않았지만, 1.7.1이 있으며 작동합니다. 그것은 설명서에 없지만 changelog는 ufuncs에 대해 이야기하고 있습니다. http://www.softpedia.com/progChangelog/Numpy-Changelog-103892.html –

+2

멋지지만, 이것이 추가되었다는 것을 몰랐습니다! – lmjohns3

4

당신은 reshape(11, 25) 후 한 번만 (빠른) mean를 호출 할 수

a.reshape(11, 25).mean(axis=1) 

을 다른 방법으로, (내 컴퓨터에 느린 배에 대한)를 두 번 np.mean를 호출 할 수

a.mean(axis=2).mean(axis=1) 
+1

을 나는하지만, 이것은 가장 간단한 대답은 생각 einsum은 더 빨라 보인다. – lmjohns3

5

항상 np.einsum 사용할 수 : 높은 차원 배열에

>>> a = np.arange(11*5*5).reshape(11,5,5) 
>>> np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2]) 
array([ 12, 37, 62, 87, 112, 137, 162, 187, 212, 237, 262]) 

작품 (이 모든 방법은 축 레이블을 변경 할 경우) :

>>> a = np.arange(10*11*5*5).reshape(10,11,5,5) 
>>> (np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2])).shape 
(10, 11) 

빠른 부팅 :

a = np.arange(11*5*5).reshape(11,5,5) 

%timeit a.reshape(11, 25).mean(axis=1) 
10000 loops, best of 3: 21.4 us per loop 

%timeit a.mean(axis=(1,2)) 
10000 loops, best of 3: 19.4 us per loop 

%timeit np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2]) 
100000 loops, best of 3: 8.26 us per loop 

배열 크기가 커짐에 따라 다른 방법보다 조금 더 잘 조정됩니다.

그래서 그냥 한 번 확인에 상당히 위의 타이밍을 변경하지 않습니다 dtype=np.float64 사용 : 재미

또한
a = np.arange(110*50*50,dtype=np.float64).reshape(110,50,50) 

%timeit a.reshape(110,2500).mean(axis=1) 
1000 loops, best of 3: 307 us per loop 

%timeit a.mean(axis=(1,2)) 
1000 loops, best of 3: 308 us per loop 

%timeit np.einsum('...ijk->...i',a)/(a.shape[-1]*a.shape[-2]) 
10000 loops, best of 3: 145 us per loop 

뭔가 :

%timeit np.sum(a) #37812362500.0 
100000 loops, best of 3: 293 us per loop 

%timeit np.einsum('ijk->',a) #37812362500.0 
100000 loops, best of 3: 144 us per loop 
+1

'np.mean'이 사용하는 확실하지 않은'float' 또는'double' 대신'int' 누산기를 사용하여'np.einsum' 호출 속도가 다가오고 있다고 생각합니다. 이것은 누적기를 초과하여 매우 잘못된 결과를 얻을 수 있기 때문에 컴퓨팅 통계와 관련하여 위험한 일입니다. 'np.einsum'에'dtype = np.float' 또는'dtype = np.double'을 주면 계산이 더욱 강력해질 것이고 (표준 함수와 성능면에서 더 비슷합니다) 추측하고 있습니다. 하지만 'np.einsum'은 여전히 ​​훌륭한 기능이므로 +1을 받으십시오. – Jaime

+0

@Jamie. 저도 제 생각이었습니다. 그러나 초기 테스트에서 'einsum'은 실제로 어떤 크기 및 dtype에서도 더 빨랐습니다.게시물을 'np.double'타이밍으로 업데이트했습니다. – Daniel

+0

@Ophion ...'sum()'이'einsum()'과 같은 속도를주지 않는다는 것이 이상합니다. 실제로는 두 번째로 빠른 방법은'timeit a.sum (축 = (1,2))/a.shape [-1] /a.shape [-2]' –