2015-01-16 2 views
5

좋아, 일부 검색 후 나는이 문제를 직접 해결할 수있는 질문을 찾을 수 없습니다. 나는 가면을 쓴 배열을 조사해 보았다. 비록 그들이 시원하게 보일지라도, 나는 그들이 필요한 것인지 확실하지 않다.파이썬 numpy 마스크 평균 성능

zone_data 동일한 값을 가진 요소 덩어리와 NumPy와 2-D 배열이다

2 개 NumPy와 배열을 고려한다. 이것은 내 '영역'입니다.

value_data은 임의의 값을 갖는 2 차원 숫자 배열 (정확한 zone_data 모양)입니다.

영역 번호 대신 각 영역의 평균값을 가진 zone_data/value_data와 같은 모양의 번호가있는 배열을 찾습니다.

예 ... 아스키 예술 형식입니다.

zone_data (4 별개의 영역) :

1, 1, 2, 2 
1, 1, 2, 2 
3, 3, 4, 4 
3, 4, 4, 4 

value_data :

1, 2, 3, 6 
3, 0, 2, 5 
1, 1, 1, 0 
2, 4, 2, 1 

내 결과, 그것은 result_data 전화 :

1.5, 1.5, 4.0, 4.0 
1.5, 1.5, 4.0, 4.0 
2.0, 2.0, 1.0, 1.0 
2.0, 2.0, 1.0, 1.0 

여기 내가 가지고있는 코드입니다. 나에게 완벽한 결과를주는 한 잘 작동합니다.

result_data = np.zeros(zone_data.shape) 
for i in np.unique(zone_data): 
    result_data[zone_data == i] = np.mean(value_data[zone_data == i]) 

내 배열이 크고 코드 조각이 몇 초 걸립니다. 나는 지식 격차가 있고 도움이되는 어떤 것도 치지 않았다고 생각한다. 루프 측면은 라이브러리 또는 무언가로 위임되어야합니다 ... aarg!

나는 이걸 더 빨리 만들 수 있도록 도움을 구한다! 파이썬 신들, 너의 지혜를 구한다!

편집 - 추가 벤치 마크 스크립트

import numpy as np 
import time 

zones = np.random.randint(1000, size=(2000,1000)) 
values = np.random.rand(2000,1000) 

print 'start method 1:' 
start_time = time.time() 

result_data = np.zeros(zones.shape) 
for i in np.unique(zones): 
    result_data[zones == i] = np.mean(values[zones == i]) 

print 'done method 1 in %.2f seconds' % (time.time() - start_time) 

print 
print 'start method 2:' 
start_time = time.time() 

#your method here! 

print 'done method 2 in %.2f seconds' % (time.time() - start_time) 

내 출력 :

start method 1: 
done method 1 in 4.34 seconds 

start method 2: 
done method 2 in 0.00 seconds 

답변

3

당신은 np.bincount을 사용할 수

count = np.bincount(zones.flat) 
tot = np.bincount(zones.flat, weights=values.flat) 
avg = tot/count 
result_data2 = avg[zones] 

나에게 좋은 관측이다

start method 1: 
done method 1 in 3.13 seconds 

start method 2: 
done method 2 in 0.01 seconds 
>>> 
>>> np.allclose(result_data, result_data2) 
True 
+0

'bincount'를 잘 사용합니다.+1 –

+0

DSM, 멋지다! 나는 나 자신을 찾기 위해 오랜 시간이 걸렸을 몇 가지 구체적인 지식을 공유 할 수있는 자신과 같은 사람들 때문에 주로 그렇게 사랑합니다. 정말 고맙습니다! 이것은 사소한 운동이 아니 었습니다 ... 이것은 응용 프로그램에서 가지고있는 병목 중 하나를 열 것입니다. 사랑 "np.allclose"도 ... 무슨 보석. – user1269942

1

가 나는 곳 scipy이 본했다고 생각하지만, 난 더 이상 그것을 찾을 수 없습니다. 거기 보셨어요?

어쨌든, 당신은 당신의 루프를 변경하여 최초의 향상을 얻을 수 있습니다 :

result_data = np.empty(zones.shape) # minor speed gain 
for label in np.unique(zones): 
    mask = zones==label 
    result_data[mask] = np.mean(values[mask]) 

당신이 불필요하게 두 번 부울 비교를하지 않는 방법. 실행 시간을 조금 줄일 수 있습니다.

+0

을 제공한다. 제 경우에는 약 40 %를 절약 할 수 있습니다 ... 훌륭한 것이고 나는 더 잘 알려야했습니다 ... 나는 다른 많은 곳에서 그렇게했습니다. DSM의 대답은 100 배 이상 빨라진다. – user1269942