2016-03-12 73 views
-1

的中線的numpy的陣列替換無值我產生數據缺失Python的 - 如何與相鄰的元素

A = np.zeros((80,80)) 
for i in range(80): 
    if i%2 == 0: 
     for j in range(80): 
      A[i,j] = None 
      if j%2 == 0: 
       A[i,j] = 50+i+j 
    else: 
     for j in range(80): 
      A[i,j] = None 
      if j%2 != 0: 
       A[i,j] = 50+i+j 

數組,給了我這個下面的截圖。

enter image description here

我想要做的是與不是無值以及相鄰元素的中間值全部替換「無」的值。 是否有一個簡單的方法來做到這一點沒有在遍歷每個元素去?

+0

也許你可以使用屏蔽數組? http://docs.scipy.org/doc/numpy/reference/maskedarray.generic.html – maazza

回答

0

爲了簡便起見,這顯示瞭如何在與正上方和正下方的元件中值填補。剩餘的2的情況下(或6,這取決於如何定義「相鄰」)是類似的。

與矩陣A開始,移動「向上」沿垂直軸元素可以

up = np.roll(A, 1, axis=0) 
up[0, :] = np.nan 
>>> up 
array([[ nan, nan, nan, ..., nan, nan, nan], 
     [ 50., nan, 52., ..., nan, 128., nan], 
     [ nan, 52., nan, ..., 128., nan, 130.], 
     ..., 
     [ 126., nan, 128., ..., nan, 204., nan], 
     [ nan, 128., nan, ..., 204., nan, 206.], 
     [ 128., nan, 130., ..., nan, 206., nan]]) 

同樣可以發現,

down = np.roll(A, -1, axis=0) 
down[-1, :] = np.nan 
>>> down 
array([[ nan, 52., nan, ..., 128., nan, 130.], 
     [ 52., nan, 54., ..., nan, 130., nan], 
     [ nan, 54., nan, ..., 130., nan, 132.], 
     ..., 
     [ 128., nan, 130., ..., nan, 206., nan], 
     [ nan, 130., nan, ..., 206., nan, 208.], 
     [ nan, nan, nan, ..., nan, nan, nan]]) 

由於這是numpy的,你可以創建一個3D使用這些2(或更多)陣列輕鬆排列

np.array([up, down]) 

有了這個陣列Y,我們可以採取np.nanmedian沿0軸(這僅僅是每個downup):

np.nanmedian(np.array([up, down]), axis=0) 

爲了填補缺失的值在A,使用

A[np.isnan(A)] = np.nanmedian(np.array([up, down]), axis=0)[np.isnan(A)] 

P.S.由於所有的鄰居可以把所有的組合軸= 0之間,-1 1,0,1個轉移(0,0移是元件本身,這將不被使用無論如何由於該isnan)中找到,則可以用雙循環自動創建所有這些二維數組。

0

我基於numba寫這樣的事情(儘管它是蒙面陣列,但我很快就適應了它的NaN)。

正如Ami Tavory所說,你也可以用一些numpy技巧來做到這一點,但如果你自己編寫循環,然後對其進行優化,我會發現它更清晰(如果沒有內建的話)。我選擇numba因爲即使它在某些方面它是非常適合加速這種for循環的限制。

import numba as nb 
import numpy as np 

@nb.njit 
def median_filter_2d(array, filtersize): 
    x = array.shape[0] 
    y = array.shape[1] 
    filter_half = filtersize // 2 
    # Create an empty result 
    res = np.zeros_like(array) 
    # Loop through each pixel 
    for i in range(x): 
     for j in range(y): 
      # If it's not NaN just let it stay 
      if not np.isnan(array[i, j]): 
       res[i, j] = array[i, j] 
      else: 
       # We don't want to go outside the image: 
       start_x = max(0, i - filter_half) 
       end_x = min(x, i + filter_half+1) 
       start_y = max(0, j - filter_half) 
       end_y = min(x, j + filter_half+1) 

       # If you want to use nanmedian uncomment this line and comment everything else following 
       #res[i, j] = np.nanmedian(array[start_x:end_x, start_y:end_y])  

       # Create a temporary array. 
       tmp = np.zeros(filtersize*filtersize) 
       counter = 0 # Counter because we want to know how many not-NaNs are present. 

       # Get all adjacent pixel that are not NaN and insert them 
       for ii in range(start_x, end_x): 
        for jj in range(start_y, end_y): 
         if not np.isnan(array[ii, jj]): 
          tmp[counter] = array[ii, jj] 
          counter += 1 

       # Either do it with np.median but it will be slower 
       #res[i, j] = np.median(tmp[0:counter]) 
       # or use some custom median-function 
       res[i, j] = numba_median_insertionsortbased(tmp[0:counter]) 
    return res 

助手值函數僅僅是一個插入排序基於排序然後返回中間元件或兩個中間元件的平均值。

@nb.njit 
def numba_median_insertionsortbased(items): 
    # Insertion sort 
    for i in range(1, len(items)): 
     j = i 
     while j > 0 and items[j] < items[j-1]: 
      items[j], items[j-1] = items[j-1], items[j] 
      j -= 1 
    # Median is the middle element (odd length) or the mean of the two middle elements (even length) 
    if items.size % 2 == 0: 
     return 0.5 * (items[(items.size // 2)-1] + items[(items.size // 2)]) 
    else: 
     return items[(items.size // 2)] 

如果你不想使用numba或不能你可以刪除@nb.njit線和純Python中使用它。它會慢很多,但它仍然可以工作。

對於一個80×80 A我得到numba計時:

1000次循環,最好3:每循環(自定義值)

100環,1.63毫秒最好的3:每圈4.88毫秒(numpy median)

但是對於大型過濾器,numpy中值會稍微快一些,因爲他們(希望)比insertionsort有更高級的方法。但是對於你的數組,元素將在臨時數組中排序,所以基於插入數據的中位數顯然是最合適的。對於真實圖像,它可能會比numpy中位數慢。

和純蟒:

1循環,最好的3:每次循環(自定義中位數)

1循環,最好的3 406個MS:每循環707毫秒(numpy的nanmedian無內循環和臨時數組)

1循環,最好的3:832毫秒每環(臨時數組numpy的中位數)

作爲旁白:我總是覺得它surprisi NG是類似的東西定製的中位數,即使沒有numba比對小維的投入numpy的中位數(好吧,他們已經排序所以它插入排序:-)的最好的情況下)更快:

%timeit numba_median_insertionsortbased(np.arange(9)) # without the @nb.njit 
10000 loops, best of 3: 21.7 µs per loop 
%timeit np.median(np.arange(9)) 
10000 loops, best of 3: 123 µs per loop 

,這些連更快的解決方案可以通過numba加速:

%timeit numba_median_insertionsortbased(np.arange(9)) # WITH the @nb.njit 
100000 loops, best of 3: 8.93 µs per loop