Ответ 1
в словах:
Гауссовский фильтр, который игнорирует NaN в заданном массиве U, можно легко получить, применив стандартный гауссовский фильтр к двум вспомогательным массивам V и W и взяв их соотношение, чтобы получить результат Z.
Здесь V - копия исходного U с заменой NaN на нули, а W - массив единиц с нулями, указывающий положение NaNs в исходном U.
Идея состоит в том, что замена NaN на нули вводит ошибку в отфильтрованном массиве, который, однако, может быть скомпенсирован путем применения того же гауссовского фильтра к другому вспомогательному массиву и объединения двух.
в Python:
import scipy as sp
import scipy.ndimage
U=sp.randn(10,10) # random array...
U[U<2]=np.nan # ...with NaNs for testing
V=U.copy()
V[U!=U]=0
VV=sp.ndimage.gaussian_filter(V,sigma=2.0)
W=0*U.copy()+1
W[U!=U]=0
WW=sp.ndimage.gaussian_filter(W,sigma=2.0)
Z=VV/WW
в цифрах:
Здесь коэффициенты гауссовского фильтра установлены для [0.25,0.50,0.25] для демонстрационных целей и суммируются до одного 0,25 + 0,50 + 0,25 = 1 без потери общности.
После замены NaN на нули и применения фильтра Гаусса (см. ниже) ясно, что нули вводят ошибку, т.е. из-за "отсутствующих" данных коэффициенты 0,25 + 0,50 = 0,75 не суммируются к одному и, следовательно, недооценивать "истинное" значение.
Однако это можно скомпенсировать, используя второй вспомогательный массив (см. WW ниже), который после фильтрации с тем же гауссовским просто содержит сумму коэффициентов.
Следовательно, разделение двух фильтрованных вспомогательных массивов масштабирует коэффициенты таким образом, что они суммируются до единицы, в то время как позиции 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