2014-09-05 43 views
0

我有一個numpy的二維數組值。數組中的每個元素表示一個網格中的一個網格點,每個網格的邊長爲13km。我需要確定網格上特定點50英里內所有點的平均值。確定點的給定半徑內網格值的平均值的最快方法

我目前的解決方案確定了一個邊界框,然後使用它們的索引引用數組中的數組中的項目,這些索引是numpy緩慢的。我試圖確定一個更快的解決方案。

當前的解決方案:

num_x = 400  #horizontal dimension of the 2D array 
num_y = 300  #vertical dimension of the 2D array 
num_dx = 6   #maximum number of horizontal grid points that fit within 50 miles 
num_dy = 6   #same as above but for vertical (square grid) 
radius_m = 80467.2 #50 miles expressed in meters 
values = []  # stores the extracted values 

for ix in range(-num_dx,num_dx+1): 
    for jy in range(-num_dy,num_dy+1): 
     # Determine distance to this point 
     dist = ((ix*dx)**2+(jy*dy)**2)**0.5 
     if dist <= radius_m: 
      # Ensure this grid point actually exists within the grid 
      if (j+jy) < num_y and (i+ix) < num_x: 
       value = myarray[i+ix,j+jy] 
        if value is not masked and value >= 0: 
         values.append(float(value)) 

average = sum(values)/float(len(values)) 

這是緩慢(約需1.5秒)由於訪問myarray中超過100倍,以提取一個單一的元素的值。有沒有一種矢量方法可以在這裏更好地工作?我似乎無法找出一種方法來使用掩碼,因爲條件是基於網格點相對於另一個的位置,而不是元素本身的值。

+0

你爲什麼不切片數組? – 2014-09-05 17:21:27

+0

我不確定你的意思。你能提供一個例子嗎? – TheOx 2014-09-05 18:40:55

+0

這樣想:對於圓上的每個點,還有3個其他點的大小完全相同,但組件上的符號不同。 – 2014-09-05 18:48:45

回答

1

您的代碼不可運行,並且似乎包含i < num_dxj < num_dy(然後它繞回到數組的另一側)的錯誤。但對你的變量名做一些假設,這是我該怎麼做的:

# First make sure we stay in the grid 
i1, i2 = max(i-num_dx, 0), min(i+num_dx+1, num_x) 
j1, j2 = max(j-num_dy, 0), min(j+num_dy+1, num_y) 

# Get the radius in blocks, grid should be homogeneous 
radius_i = radius_m/13000.0 

# Calc distances per element by broadcasting 
DX = np.arange(i1, i2) - i 
DY = np.arange(j1, j2)[:, None] - j 
mask = DX*DX + DY*DY <= radius_i*radius_i 

# Get block of interest and apply mask 
values = myarray[i1:i2, j1:j2][mask] 
1

對於內部點(半徑不會超出圖像範圍),您可以計算一個用於任何內部點的單個蒙版。開始用零的數組:

mask = np.zeros((2 * num_dx + 1, 2 * num_dy + 1), dtype=np.int) 

假設你的興趣點是在該陣列的中心,設置的半徑內下降到1(這裏未示出)的每個元素。然後,

indices = np.argwhere(mask.ravel() == 1) 

那麼對於任何內部元素(i, j)myarray,你會喜歡的半徑範圍內獲取值:

values = myarray[i-num_dx: i+num_dx+1, j-num_dy: j+num_dy+1].ravel()[indices] 

對於邊界附近的點,你會作出的mask和一套複印件在設置indices之前,將圖像外部的行/列置零。