Python 循环聚集屏蔽索引

Python 循环聚集屏蔽索引,python,numpy,masked-array,Python,Numpy,Masked Array,我有一个数组y\u filtered,其中包含一些屏蔽值。我想将这些值替换为我根据其相邻值计算的值。我可以通过使用masked\u slices=ma.clump\u masked(y\u filtered)来获得屏蔽值的索引。这将返回一个切片列表,例如[切片(194196,无)] 通过使用y\u筛选的[masked\u切片],我可以很容易地从我的屏蔽数组中获取值,甚至可以循环它们。但是,我还需要访问这些值的索引,这样我就可以根据它的邻居计算它的新值。枚举(逻辑)返回0、1等,而不是我需要的索引

我有一个数组
y\u filtered
,其中包含一些屏蔽值。我想将这些值替换为我根据其相邻值计算的值。我可以通过使用
masked\u slices=ma.clump\u masked(y\u filtered)
来获得屏蔽值的索引。这将返回一个切片列表,例如
[切片(194196,无)]

通过使用
y\u筛选的[masked\u切片]
,我可以很容易地从我的屏蔽数组中获取值,甚至可以循环它们。但是,我还需要访问这些值的索引,这样我就可以根据它的邻居计算它的新值。枚举(逻辑)返回0、1等,而不是我需要的索引

这是我想出的解决办法

# get indices of masked data
masked_slices = ma.clump_masked(y_filtered)

y_enum = [(i, y_i) for i, y_i in zip(range(len(y_filtered)), y_filtered)]

for sl in masked_slices:
    for i, y_i in y_enum[sl]:
        # simplified example calculation
        y_filtered[i] = np.average(y_filtered[i-2:i+2])
这是一种非常丑陋的i.m.o.方法,我认为必须有更好的方法来做到这一点。有什么建议吗

谢谢

编辑:

我想出了一个更好的方法来实现我认为你想做的事情。这段代码选取包含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\u filtered
中的值,因此后续索引的结果受先前迭代的影响,这可以通过原始
y\u 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])

您是在尝试使用每个索引周围的非屏蔽值平滑
y_filtered
,还是同时使用屏蔽值和非屏蔽值?我最后使用
ma.compressed
删除所有屏蔽数据,然后使用scipy插值缺少的值。我仍然对如何进行循环感兴趣。我用一个没有循环的有效解决方案编辑了我的答案。你说得对,我的代码确实有一些错误。我遗漏了一些不相关的零碎内容,没有测试我在这里发布的内容。显然,我疏忽了。我最终选择了numpy的线性插值。线性插值对于我来说已经足够好了,我需要每个数据点都有一个值。我认为numpy返回切片列表而不是索引列表的方法在某些情况下有点笨拙。另一方面,如果你的切片很大,那么索引列表也不是你想要的。不管怎样,我今天学到了一些东西。谢谢