子类化numpy.ma.MaskedArray

时间:2013-01-28 14:53:59

标签: python numpy

我正在尝试将numpy的MaskedArray子类化为添加属性,但似乎无法获得正确的结果。

我开始关注the example以便对numpy.ndarray进行子类化,效果很好。

然后我尝试了对numpy.ma.MaskedArray进行子类化,如下所示:

import numpy as np

class MyMaskedArray(np.ma.MaskedArray):

    def __new__(cls, input_array, info=None):
        obj = np.asarray(input_array).view(cls)
        obj.info = info
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.info = getattr(obj, 'info', None)
        super(MyMaskedArray, self).__array_finalize__(obj)

arr = np.arange(5)
obj = MyMaskedArray(arr, info='information')
print obj.info
print obj[1:].info

导致

information
None

我曾两次预期“信息”。

obj = np.asarray(input_array).view(cls)obj = np.ma.MaskedArray(input_array).view(cls)替换行obj = np.ma.MaskedArray.__new__(cls, input_array)并没有解决问题(我这样做了,因为我想传递*args和{{在未来的子类化身中,1}}到**kwargs。)

请注意,我还必须在我的子类“__new__中添加对MaskedArray.__array_finalize的调用,而不是__array_finalize__子类的示例;如果我不这样做,则找不到ndarray属性。

也许有人可以启发我:

  • 如何让_mask保留原始obj[1:].info

  • 为什么obj.info不需要ndarray的超级电话,但是__array_finalize__会更多(更多的是奖金问题)。

我想继承MaskedArray而不是编写容器类,因为后者会失去MaskedArray附带的一些便利。

(注意:这与this question不同,因为我已“解决”了MaskedArray / __init__问题。)

1 个答案:

答案 0 :(得分:2)

为了让切片按照您的意愿工作,您可能需要重载__getitem__

def __getitem__(self, item):
    out = np.ma.MaskedArray.__getitem__(self, item)
    out.info = self.info
    return out

同样为__setitem__

如果您的info属性相对简单,例如在您的示例中,您可能需要查看专为此目的而设计的_optinfo MaskedArray属性:它只是存储一些必须以某种方式保存的信息的字典。这是一个例子:

class MyMaskedArray(np.ma.MaskedArray):

    def __new__(cls, input_array, info=None):
        obj = np.asarray(input_array).view(cls)
        obj._optinfo['info'] = info
        return obj

    @property
    def info(self):
        return self._optinfo.get('info', None)

请注意,.info是一个只读属性,但它可以直接使其可写。

关于 __array_finalize__

我不确定我理解你的问题:ndarray本身就是超类。 MaskedArrayndarray的子类,因此需要定义一个__array_finalize__方法,该方法特别告诉如何设置掩码(通过_mask参数)。有关子类化的更多信息,请查看此link

在您的示例中,您使用自己的__array_finalize__来设置.info属性。在这种情况下,您必须调用父方法MaskedArray.__array_finalize__,它是基本的Python子类。请注意,如果您采用__array_finalize__方式...

,则无需明确定义_optinfo

注意

  • __array_prepare____array_wrap__方法实际上用于在向函数应用函数之前准备ndarray子类的实例并处理函数的结果