用言语来说:
忽略给定数组中 NaN 的高斯滤波器U通过将标准高斯滤波器应用于两个辅助阵列可以轻松获得V and W并通过取两者的比率来得到结果Z.
Here, V是原件的副本UNaN 被零替换并且W是一个由 0 组成的数组,表示原始 NaN 的位置U.
这个想法是,用零替换 NaN 会在滤波后的数组中引入误差,但是,可以通过将相同的高斯滤波器应用于另一个辅助数组并将两者组合来补偿。
在Python中:
import numpy as np
import scipy as sp
import scipy.ndimage
sigma=2.0 # standard deviation for Gaussian kernel
truncate=4.0 # truncate filter at this many sigmas
U=sp.randn(10,10) # random array...
U[U>2]=np.nan # ...with NaNs for testing
V=U.copy()
V[np.isnan(U)]=0
VV=sp.ndimage.gaussian_filter(V,sigma=sigma,truncate=truncate)
W=0*U.copy()+1
W[np.isnan(U)]=0
WW=sp.ndimage.gaussian_filter(W,sigma=sigma,truncate=truncate)
Z=VV/WW
以数字表示:
这里,出于演示目的,高斯滤波器的系数被设置为[0.25,0.50,0.25],并且它们的总和为1 0.25+0.50+0.25=1,而不失一般性。
用零替换 NaN 并应用高斯滤波器(参见下面的 VV)后,很明显零会引入错误,即,由于“丢失”数据,系数 0.25+0.50=0.75 的总和不再为 1因此低估了“真实”价值。
然而,这可以通过使用第二个辅助数组(参见下面的 WW)来补偿,该数组在使用相同的高斯滤波后,仅包含系数之和。
因此,划分两个滤波后的辅助数组会重新调整系数,使其总和为 1,同时忽略 NaN 位置。
array U 1 2 NaN 1 2
auxiliary V 1 2 0 1 2
auxiliary W 1 1 0 1 1
position a b c d e
filtered VV_b = 0.25*V_a + 0.50*V_b + 0.25*V_c
= 0.25*1 + 0.50*2 + 0
= 1.25
filtered WW_b = 0.25*W_a + 0.50*W_b + 0.25*W_c
= 0.25*1 + 0.50*1 + 0
= 0.75
ratio Z = VV_b / WW_b
= (0.25*1 + 0.50*2) / (0.25*1 + 0.50*1)
= 0.333*1 + 0.666*2
= 1.666
更新 - 除以零:
以下内容包含@AndyL 和@amain 在下面的评论中提出的有用问题和答案,谢谢!
当高斯核的支持范围内只有 NaN 条目时,大面积的 NaN 可能会在某些位置导致分母为零(WW = 0)(理论上支持是无限的,但实际上核通常会被截断,请参见'上面代码示例中的截断'参数)。在这种情况下,提名器也会变为零(VV=0),因此 numpy 会抛出“RuntimeWarning:true_divide 中遇到无效值”并在相应位置返回 NaN。
这可能是最一致/最有意义的结果,如果您可以忍受麻木的警告,则无需进一步调整。