反转 "numpy.ma.compressed" 操作
Inverting the "numpy.ma.compressed" operation
我想从压缩的掩码数组和相应的掩码创建一个数组。用一个例子更容易解释这一点:
>>> x=np.ma.array(np.arange(4).reshape((2,2)), mask = [[True,True],[False,False]])
>>> y=x.compressed()
>>> y
array([ 2, 3])
现在我想创建一个与 x 形状相同的数组,其中掩码值获得标准值(例如 -1),其余部分填充给定数组。它应该像这样工作:
>>> z = decompress(y, mask=[[True,True],[False,False]], default=-1)
>>> z
array([[-1, -1],
[ 2, 3]])
问题是:有没有类似"decompress"的方法,还是需要自己编码?在 Fortran 中,这是通过方法 "pack" 和 "unpack" 完成的。
感谢您的任何建议。
虽然我已经回答了一些 ma
问题,但我绝不是这方面的专家。但我会探讨这个问题
让我们概括一下您的数组:
In [934]: x=np.ma.array(np.arange(6).reshape((2,3)), mask = [[True,True,False],[False,False,True]])
In [935]: x
Out[935]:
masked_array(data =
[[-- -- 2]
[3 4 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [936]: y=x.compressed()
In [937]: y
Out[937]: array([2, 3, 4])
y
除了值的子集外,没有关于 x
的信息。注意是 1d
x
将其值存储在 2 个数组中(实际上这些是访问基础 ._data
、._mask
属性的属性):
In [938]: x.data
Out[938]:
array([[0, 1, 2],
[3, 4, 5]])
In [939]: x.mask
Out[939]:
array([[ True, True, False],
[False, False, True]], dtype=bool)
我猜想 de-compress
我们需要用正确的数据类型、形状和掩码创建一个 empty
掩码数组,并将 y
的值复制到它的 data
。但是 data
的掩码元素应该放入什么值呢?
或者另一种解决问题的方式 - 是否可以将值从 y
复制回 x
?
一个可能的解决方案是将新值复制到 x[~x.mask]
:
In [957]: z=2*y
In [958]: z
Out[958]: array([4, 6, 8])
In [959]: x[~x.mask]=z
In [960]: x
Out[960]:
masked_array(data =
[[-- -- 4]
[6 8 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [961]: x.data
Out[961]:
array([[0, 1, 4],
[6, 8, 5]])
或者创建一个新数组
In [975]: w=np.zeros_like(x)
In [976]: w[~w.mask]=y
In [977]: w
Out[977]:
masked_array(data =
[[-- -- 2]
[3 4 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [978]: w.data
Out[978]:
array([[0, 0, 2],
[3, 4, 0]])
另一种方法是创建一个常规数组,full
包含无效值,像这样复制 y
,然后将整个数组变成一个屏蔽数组。可能存在一个掩码数组构造函数,它允许您仅指定有效值和掩码。但是我必须为此深入研究文档。
===============
将执行此操作的另一个操作序列,使用 np.place
设置值
In [1011]: w=np.empty_like(x)
In [1014]: np.place(w,w.mask,999)
In [1015]: np.place(w,~w.mask,[1,2,3])
In [1016]: w
Out[1016]:
masked_array(data =
[[-- -- 1]
[2 3 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [1017]: w.data
Out[1017]:
array([[999, 999, 1],
[ 2, 3, 999]])
====================
看看
https://github.com/numpy/numpy/blob/master/numpy/ma/core.py
class _MaskedBinaryOperation:
此class用于实现屏蔽ufunc
。它评估有效单元格(非屏蔽)的 ufunc
和 returns 一个具有有效单元格的新屏蔽数组,使屏蔽值保持不变(与原始)
例如,对于一个简单的掩码数组,+1
不会更改掩码值。
In [1109]: z=np.ma.masked_equal([1,0,2],0)
In [1110]: z
Out[1110]:
masked_array(data = [1 -- 2],
mask = [False True False],
fill_value = 0)
In [1111]: z.data
Out[1111]: array([1, 0, 2])
In [1112]: z+1
Out[1112]:
masked_array(data = [2 -- 3],
mask = [False True False],
fill_value = 0)
In [1113]: _.data
Out[1113]: array([2, 0, 3])
In [1114]: z.compressed()+1
Out[1114]: array([2, 3])
_MaskedUnaryOperation
可能更容易理解,因为它只需要使用 1 个掩码数组。
例如,常规日志在屏蔽 0 值方面存在问题:
In [1115]: z.log()
...
/usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in log
#!/usr/bin/python3
Out[1116]:
masked_array(data = [0.0 -- 0.6931471805599453],
mask = [False True False],
fill_value = 0)
但屏蔽日志跳过屏蔽条目:
In [1117]: np.ma.log(z)
Out[1117]:
masked_array(data = [0.0 -- 0.6931471805599453],
mask = [False True False],
fill_value = 0)
In [1118]: _.data
Out[1118]: array([ 0. , 0. , 0.69314718])
糟糕 - _MaskedUnaryOperation
可能没那么有用。它在所有值 np.ma.getdata(z)
处评估 ufunc
,并使用 errstate
上下文来阻止警告。然后它使用掩码将掩码值复制到结果 (np.copyto(result, d, where=m)
)。
我想从压缩的掩码数组和相应的掩码创建一个数组。用一个例子更容易解释这一点:
>>> x=np.ma.array(np.arange(4).reshape((2,2)), mask = [[True,True],[False,False]])
>>> y=x.compressed()
>>> y
array([ 2, 3])
现在我想创建一个与 x 形状相同的数组,其中掩码值获得标准值(例如 -1),其余部分填充给定数组。它应该像这样工作:
>>> z = decompress(y, mask=[[True,True],[False,False]], default=-1)
>>> z
array([[-1, -1],
[ 2, 3]])
问题是:有没有类似"decompress"的方法,还是需要自己编码?在 Fortran 中,这是通过方法 "pack" 和 "unpack" 完成的。 感谢您的任何建议。
虽然我已经回答了一些 ma
问题,但我绝不是这方面的专家。但我会探讨这个问题
让我们概括一下您的数组:
In [934]: x=np.ma.array(np.arange(6).reshape((2,3)), mask = [[True,True,False],[False,False,True]])
In [935]: x
Out[935]:
masked_array(data =
[[-- -- 2]
[3 4 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [936]: y=x.compressed()
In [937]: y
Out[937]: array([2, 3, 4])
y
除了值的子集外,没有关于 x
的信息。注意是 1d
x
将其值存储在 2 个数组中(实际上这些是访问基础 ._data
、._mask
属性的属性):
In [938]: x.data
Out[938]:
array([[0, 1, 2],
[3, 4, 5]])
In [939]: x.mask
Out[939]:
array([[ True, True, False],
[False, False, True]], dtype=bool)
我猜想 de-compress
我们需要用正确的数据类型、形状和掩码创建一个 empty
掩码数组,并将 y
的值复制到它的 data
。但是 data
的掩码元素应该放入什么值呢?
或者另一种解决问题的方式 - 是否可以将值从 y
复制回 x
?
一个可能的解决方案是将新值复制到 x[~x.mask]
:
In [957]: z=2*y
In [958]: z
Out[958]: array([4, 6, 8])
In [959]: x[~x.mask]=z
In [960]: x
Out[960]:
masked_array(data =
[[-- -- 4]
[6 8 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [961]: x.data
Out[961]:
array([[0, 1, 4],
[6, 8, 5]])
或者创建一个新数组
In [975]: w=np.zeros_like(x)
In [976]: w[~w.mask]=y
In [977]: w
Out[977]:
masked_array(data =
[[-- -- 2]
[3 4 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [978]: w.data
Out[978]:
array([[0, 0, 2],
[3, 4, 0]])
另一种方法是创建一个常规数组,full
包含无效值,像这样复制 y
,然后将整个数组变成一个屏蔽数组。可能存在一个掩码数组构造函数,它允许您仅指定有效值和掩码。但是我必须为此深入研究文档。
===============
将执行此操作的另一个操作序列,使用 np.place
设置值
In [1011]: w=np.empty_like(x)
In [1014]: np.place(w,w.mask,999)
In [1015]: np.place(w,~w.mask,[1,2,3])
In [1016]: w
Out[1016]:
masked_array(data =
[[-- -- 1]
[2 3 --]],
mask =
[[ True True False]
[False False True]],
fill_value = 999999)
In [1017]: w.data
Out[1017]:
array([[999, 999, 1],
[ 2, 3, 999]])
====================
看看
https://github.com/numpy/numpy/blob/master/numpy/ma/core.py
class _MaskedBinaryOperation:
此class用于实现屏蔽ufunc
。它评估有效单元格(非屏蔽)的 ufunc
和 returns 一个具有有效单元格的新屏蔽数组,使屏蔽值保持不变(与原始)
例如,对于一个简单的掩码数组,+1
不会更改掩码值。
In [1109]: z=np.ma.masked_equal([1,0,2],0)
In [1110]: z
Out[1110]:
masked_array(data = [1 -- 2],
mask = [False True False],
fill_value = 0)
In [1111]: z.data
Out[1111]: array([1, 0, 2])
In [1112]: z+1
Out[1112]:
masked_array(data = [2 -- 3],
mask = [False True False],
fill_value = 0)
In [1113]: _.data
Out[1113]: array([2, 0, 3])
In [1114]: z.compressed()+1
Out[1114]: array([2, 3])
_MaskedUnaryOperation
可能更容易理解,因为它只需要使用 1 个掩码数组。
例如,常规日志在屏蔽 0 值方面存在问题:
In [1115]: z.log()
...
/usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in log
#!/usr/bin/python3
Out[1116]:
masked_array(data = [0.0 -- 0.6931471805599453],
mask = [False True False],
fill_value = 0)
但屏蔽日志跳过屏蔽条目:
In [1117]: np.ma.log(z)
Out[1117]:
masked_array(data = [0.0 -- 0.6931471805599453],
mask = [False True False],
fill_value = 0)
In [1118]: _.data
Out[1118]: array([ 0. , 0. , 0.69314718])
糟糕 - _MaskedUnaryOperation
可能没那么有用。它在所有值 np.ma.getdata(z)
处评估 ufunc
,并使用 errstate
上下文来阻止警告。然后它使用掩码将掩码值复制到结果 (np.copyto(result, d, where=m)
)。