在numpy数组之外切片

时间:2015-09-16 09:36:12

标签: python numpy

给出一个2d矩阵,例如:

A = array([[ 0,  1,  2,  3],
          [ 4,  5,  6,  7],
          [ 8,  9, 10, 11],
          [12, 13, 14, 15]])

如何在给定元素周围选择NxN窗口,以便如果窗口超出原始数组,窗口将填充任意(例如均值)值?

示例:

neighbors(A, x=0, y=0, N=3)

会产生

array([[ 2.5,  2.5,  2.5],
       [ 2.5,    0,    1],
       [ 2.5,    4,    5]])

3 个答案:

答案 0 :(得分:6)

你可以pad你的阵列。填充将使用所需的边界条件扩展数组(有关所有可能选项,请参阅mode参数):

>>> A = np.array([[ 0,  1,  2,  3],
                  [ 4,  5,  6,  7],
                  [ 8,  9, 10, 11],
                  [12, 13, 14, 15]])
>>> N = 5 # 5x5 windows
>>> B = np.pad(A, N//2, mode='reflect')
>>> B
array([[10,  9,  8,  9, 10, 11, 10,  9],
       [ 6,  5,  4,  5,  6,  7,  6,  5],
       [ 2,  1,  0,  1,  2,  3,  2,  1],
       [ 6,  5,  4,  5,  6,  7,  6,  5],
       [10,  9,  8,  9, 10, 11, 10,  9],
       [14, 13, 12, 13, 14, 15, 14, 13],
       [10,  9,  8,  9, 10, 11, 10,  9],
       [ 6,  5,  4,  5,  6,  7,  6,  5]])

如您所见,原始数组位于矩阵的中心,由2行2列(N//2 = 5//2 = 2填充,均来自lef / right和bottom / top)。填充元素反映

对于这个新数组,您可以通过正常索引数组来访问所需的邻居窗口:

>>> x = 1; y = 1 # corresponds to number 5 in the original array
>>> B[y:y+N, x:x+N]
array([[ 5,  4,  5,  6,  7],
       [ 1,  0,  1,  2,  3],
       [ 5,  4,  5,  6,  7],
       [ 9,  8,  9, 10, 11],
       [13, 12, 13, 14, 15]])

您可以选择其他填充方法,意味着是其中一个选项。

答案 1 :(得分:2)

我认为这并不太遥远:

def neighbors(arr, x, y, N):
    left = max(0, x - N)
    right = min(arr.shape[0], x + N)
    top = max(0, y - N)
    bottom = min(arr.shape[1], y + N)

    window = arr[left:right+1,top:bottom+1]
    fillval = window.mean()

    result = np.empty((2*N+1, 2*N+1))
    result[:] = fillval

    ll = N - x
    tt = N - y
    result[ll+left:ll+right+1,tt+top:tt+bottom+1] = window

    return result

答案 2 :(得分:2)

这是np.lib.padnp.ix_ -

的一种方式
Ap = np.lib.pad(A.astype(float),1, 'constant', constant_values=(np.nan,np.nan))
Acut = Ap[np.ix_(np.arange(N)+x,np.arange(N)+y)]
Acut[np.isnan(Acut)] = np.nanmean(Acut)

示例运行 -

In [76]: A
Out[76]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

In [77]: x=1; y=0; N = 3

In [78]: Ap = np.lib.pad(A.astype(float),1, 'constant', constant_values=(np.nan,np.nan))
    ...: Acut = Ap[np.ix_(np.arange(N)+x,np.arange(N)+y)]
    ...: Acut[np.isnan(Acut)] = np.nanmean(Acut)
    ...: 

In [79]: Acut
Out[79]: 
array([[ 4.5,  0. ,  1. ],
       [ 4.5,  4. ,  5. ],
       [ 4.5,  8. ,  9. ]])