2017-09-04 17 views
1

voronoi binning을 사용했습니다. 각 빈에 대한 중앙 좌표가 있으며 각 빈에 포함 된 모든 픽셀의 평균을 찾고 싶습니다. 난 그저 numpy 어레이를 벡터 라이 제이션 (vectorise)하기 위해 슬라이스하는 방법에 대해 고개를 갸웃 할 수는 없습니다.데이터를 비 그리드 기반 빈으로 채우기

이것은 현재 코드입니다. X 및 Y는 각 bin의 중심에 대한 x 및 y 좌표가있는 1D 배열입니다. f는 2 차원 이미지에서 :

import numpy as np 
from scipy.spatial import KDTree 

def rebin(f, X, Y): 
    s = f.shape 
    x_grid = np.arange(s[0]) 
    y_grid = np.arange(s[1]) 
    x_grid, y_grid = np.meshgrid(x_grid,y_grid) 
    x_grid, y_grid = x_grid.flatten(), y_grid.flatten() 

    tree = KDTree(zip(X,Y)) 
    _, b = tree.query(zip(x_grid, y_grid)) 
    out = X*np.nan 

    for i in range(max(b)): 
     out[i] = np.nanmean(f[x_grid[b==i], y_grid[b==i]]) 
    return out 

for 루프는 현재 막대한 병목 현상입니다. 아마 정말 간단한 대답 일 것입니다 - 저는 그 순간 그것을 볼 수 없습니다!

답변

1
out = X*np.nan 
for i in range(max(b)): 
    out[i] = np.nanmean(f[x_grid[b==i], y_grid[b==i]]) 

np.bincount에 두 통화로 대체 될 수 있습니다

total = np.bincount(b, weights=f[x_grid, y_grid], minlength=len(X)) 
count = np.bincount(b, minlength=len(X)) 
out = total/count 

또는 하나의 호출 stats.binned_statistic에 :

out, bin_edges, binnumber = stats.binned_statistic(
    x=b, values=f[x_grid, y_grid], statistic='mean', bins=np.arange(len(X)+1)) 
예를 들어

,

import numpy as np 
from scipy.spatial import KDTree 
import scipy.stats as stats 
np.random.seed(2017) 

def rebin(f, X, Y): 
    s = f.shape 
    x_grid = np.arange(s[0]) 
    y_grid = np.arange(s[1]) 
    x_grid, y_grid = np.meshgrid(x_grid,y_grid) 
    x_grid, y_grid = x_grid.flatten(), y_grid.flatten() 

    tree = KDTree(np.column_stack((X,Y))) 
    _, b = tree.query(np.column_stack((x_grid, y_grid))) 

    out, bin_edges, binnumber = stats.binned_statistic(
     x=b, values=f[x_grid, y_grid], statistic='mean', bins=np.arange(len(X)+1)) 
    # total = np.bincount(b, weights=f[x_grid, y_grid], minlength=len(X)) 
    # count = np.bincount(b, minlength=len(X)) 
    # out = total/count 
    return out 

def orig(f, X, Y): 
    s = f.shape 
    x_grid = np.arange(s[0]) 
    y_grid = np.arange(s[1]) 
    x_grid, y_grid = np.meshgrid(x_grid,y_grid) 
    x_grid, y_grid = x_grid.flatten(), y_grid.flatten() 

    tree = KDTree(np.column_stack((X,Y))) 
    _, b = tree.query(np.column_stack((x_grid, y_grid))) 

    out = X*np.nan 
    for i in range(len(X)): 
     out[i] = np.nanmean(f[x_grid[b==i], y_grid[b==i]]) 
    return out 

N = 100 
X, Y = np.random.random((2, N)) 
f = np.random.random((N, N)) 

expected = orig(f, X, Y) 
result = rebin(f, X, Y) 
print(np.allclose(expected, result, equal_nan=True)) 
# True 
0

나는 훨씬 빠른 cKDTree라는 KDTree의 완전한 버전의 cython이 있음을 발견했습니다.