Python使用na值获得矩阵中邻居的平均值

Aam*_*han 2 python numpy matrix

我有非常大的矩阵,所以不想通过遍历每一行和列来求和.

a = [[1,2,3],[3,4,5],[5,6,7]]
def neighbors(i,j,a):
    return [a[i][j-1], a[i][(j+1)%len(a[0])], a[i-1][j], a[(i+1)%len(a)][j]]
[[np.mean(neighbors(i,j,a)) for j in range(len(a[0]))] for i in range(len(a))]
Run Code Online (Sandbox Code Playgroud)

此代码适用于3x3或小范围的矩阵,但对于像2k x 2k这样的大矩阵,这是不可行的.如果矩阵中的任何值缺失或类似,这也不起作用na

此代码适用于3x3或小范围的矩阵,但对于像2k x 2k这样的大矩阵,这是不可行的.如果矩阵中的任何值缺失或类似,这也不起作用na.如果任何邻居值na然后跳过该邻居获得平均值

Div*_*kar 5

射击#1

这假设您希望在输入数组中获得滑动窗口平均值,其中窗口3 x 3仅考虑西北 - 东 - 南邻域元素.

对于这种情况,signal.convolve2d可以使用适当的内核.最后,您需要将这些求和除以内核中的求和数,即kernel.sum()仅作为求和的总和.这是实施 -

import numpy as np
from scipy import signal

# Inputs
a = [[1,2,3],[3,4,5],[5,6,7],[4,8,9]]

# Convert to numpy array
arr = np.asarray(a,float)    

# Define kernel for convolution                                         
kernel = np.array([[0,1,0],
                   [1,0,1],
                   [0,1,0]]) 

# Perform 2D convolution with input data and kernel 
out = signal.convolve2d(arr, kernel, boundary='wrap', mode='same')/kernel.sum()
Run Code Online (Sandbox Code Playgroud)

射击#2

这与假设#1中的假设相同,只是我们希望在仅零元素的邻域中找到平均值,并打算用这些平均值替换它们.

方法#1:这是使用手动选择性卷积方法实现它的一种方法 -

import numpy as np

# Convert to numpy array
arr = np.asarray(a,float)    

# Pad around the input array to take care of boundary conditions
arr_pad = np.lib.pad(arr, (1,1), 'wrap')

R,C = np.where(arr==0)   # Row, column indices for zero elements in input array
N = arr_pad.shape[1]     # Number of rows in input array

offset = np.array([-N, -1, 1, N])
idx = np.ravel_multi_index((R+1,C+1),arr_pad.shape)[:,None] + offset

arr_out = arr.copy()
arr_out[R,C] = arr_pad.ravel()[idx].sum(1)/4
Run Code Online (Sandbox Code Playgroud)

样本输入,输出 -

In [587]: arr
Out[587]: 
array([[ 4.,  0.,  3.,  3.,  3.,  1.,  3.],
       [ 2.,  4.,  0.,  0.,  4.,  2.,  1.],
       [ 0.,  1.,  1.,  0.,  1.,  4.,  3.],
       [ 0.,  3.,  0.,  2.,  3.,  0.,  1.]])

In [588]: arr_out
Out[588]: 
array([[ 4.  ,  3.5 ,  3.  ,  3.  ,  3.  ,  1.  ,  3.  ],
       [ 2.  ,  4.  ,  2.  ,  1.75,  4.  ,  2.  ,  1.  ],
       [ 1.5 ,  1.  ,  1.  ,  1.  ,  1.  ,  4.  ,  3.  ],
       [ 2.  ,  3.  ,  2.25,  2.  ,  3.  ,  2.25,  1.  ]])
Run Code Online (Sandbox Code Playgroud)

为了处理边界条件,还有其他填充选项.请查看numpy.pad更多信息.

方法#2:这将是前面列出的基于卷积的方法的修改版本Shot #1.这与之前的方法相同,只是在最后,我们选择性地用卷积输出​​替换零元素.这是代码 -

import numpy as np
from scipy import signal

# Inputs
a = [[1,2,3],[3,4,5],[5,6,7],[4,8,9]]

# Convert to numpy array
arr = np.asarray(a,float)

# Define kernel for convolution                                         
kernel = np.array([[0,1,0],
                   [1,0,1],
                   [0,1,0]]) 

# Perform 2D convolution with input data and kernel 
conv_out = signal.convolve2d(arr, kernel, boundary='wrap', mode='same')/kernel.sum()

# Initialize output array as a copy of input array
arr_out = arr.copy()

# Setup a mask of zero elements in input array and 
# replace those in output array with the convolution output
mask = arr==0
arr_out[mask] = conv_out[mask]
Run Code Online (Sandbox Code Playgroud)

备注: Approach #1当输入数组中的零元素数量较少时,将是首选方法,否则请使用Approach #2.