编辑:
我想出了一个更好的方法来实现我认为你想做的事情。此代码选取 5 个元素的每个窗口并计算其(屏蔽)平均值,然后使用这些值来填充原始数组中的空白。如果某个索引没有足够接近的任何未屏蔽值,它只会将其保留为屏蔽:
import numpy as np
from numpy.lib.stride_tricks import as_strided
SMOOTH_MARGIN = 2
x = np.ma.array(data=[1, 2, 3, 4, 5, 6, 8, 9, 10],
mask=[0, 1, 0, 0, 1, 1, 1, 1, 0])
print(x)
# [1 -- 3 4 -- -- -- -- 10]
pad_data = np.pad(x.data, (SMOOTH_MARGIN, SMOOTH_MARGIN), mode='constant')
pad_mask = np.pad(x.mask, (SMOOTH_MARGIN, SMOOTH_MARGIN), mode='constant',
constant_values=True)
k = 2 * SMOOTH_MARGIN + 1
isize = x.dtype.itemsize
msize = x.mask.dtype.itemsize
x_pad = np.ma.array(
data=as_strided(pad_data, (len(x), k), (isize, isize), writeable=False),
mask=as_strided(pad_mask, (len(x), k), (msize, msize), writeable=False))
x_avg = np.ma.average(x_pad, axis=1).astype(x_pad.dtype)
fill_mask = ~x_avg.mask & x.mask
result = x.copy()
result[fill_mask] = x_avg[fill_mask]
print(result)
# [1 2 3 4 3 4 10 10 10]
(注意这里所有的值都是整数,因为x
最初是整数类型)
原始发布的代码有一些错误,首先它y_filtered
在循环中读取和写入值,因此后来索引的结果会受到先前迭代的影响,这可以通过原始的副本来修复y_filtered
。其次,[i-2:i+2]
可能应该是[max(i-2, 0):i+3]
,以便始终具有从零或以后开始的对称窗口。
你可以这样做:
from itertools import chain
# get indices of masked data
masked_slices = ma.clump_masked(y_filtered)
for idx in chain.from_iterable(range(s.start, s.stop) for s in masked_slices):
y_filtered[idx] = np.average(y_filtered[max(idx - 2, 0):idx + 3])