子类numpy ndarray问题

时间:2011-03-01 00:38:09

标签: python numpy subclass recarray

我想继承numpy ndarray。但是,我无法更改阵列。为什么self = ...不会更改数组?感谢。

import numpy as np

class Data(np.ndarray):

    def __new__(cls, inputarr):
        obj = np.asarray(inputarr).view(cls)
        return obj

    def remove_some(self, t):
        test_cols, test_vals = zip(*t)
        test_cols = self[list(test_cols)]
        test_vals = np.array(test_vals, test_cols.dtype)

        self = self[test_cols != test_vals] # Is this part correct?

        print len(self) # correct result

z = np.array([(1,2,3), (4,5,6), (7,8,9)],
    dtype=[('a', int), ('b', int), ('c', int)])
d = Data(z)
d.remove_some([('a',4)])

print len(d)  # output the same size as original. Why?

3 个答案:

答案 0 :(得分:6)

您未获得预期结果的原因是您在方法self中重新分配remove_some。您只是创建一个新的局部变量self。如果你的数组形状没有改变,你可以简单地做自我[:] = ...你可以保持对self的引用,一切都会好,但是你试图改变{{{{{ 1}}。这意味着我们需要重新分配一些新内存,并在我们引用self时更改我们指向的位置。

我不知道该怎么做。我认为可以通过self__array_finalize____array__来实现。但我所尝试的一切都不尽如人意。

现在,还有另一种方法可以解决这个问题,而不是__array_wrap__的子类。你可以创建一个新类,它保留一个ndarray属性,然后覆盖所有常用的ndarray__add__等。这样的东西:

__mul__
嗯,你明白了。覆盖所有操作员是一种痛苦,但从长远来看,我认为更灵活。

您必须彻底阅读this才能正确行事。像Class Data(object): def __init__(self, inarr): self._array = np.array(inarr) def remove_some(x): self._array = self._array[x] def __add__(self, other): return np.add(self._array, other) 这样的方法需要被称为正确的“清理”时间。

答案 1 :(得分:4)

也许这是一个函数,而不是一个方法:

import numpy as np

def remove_row(arr,col,val):
    return arr[arr[col]!=val]

z = np.array([(1,2,3), (4,5,6), (7,8,9)],
    dtype=[('a', int), ('b', int), ('c', int)])

z=remove_row(z,'a',4)
print(repr(z))

# array([(1, 2, 3), (7, 8, 9)], 
#       dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<i4')])

或者,如果你想把它当作一种方法,

import numpy as np

class Data(np.ndarray):

    def __new__(cls, inputarr):
        obj = np.asarray(inputarr).view(cls)
        return obj

    def remove_some(self, col, val):
        return self[self[col] != val]

z = np.array([(1,2,3), (4,5,6), (7,8,9)],
    dtype=[('a', int), ('b', int), ('c', int)])
d = Data(z)
d = d.remove_some('a', 4)
print(d)

这里的关键区别是remove_some不会尝试修改self,它只会返回Data的新实例。

答案 2 :(得分:3)

我尝试做同样的事情,但是将ndarray子类化为非常复杂。

如果你只需要添加一些功能,我建议创建一个将数组存储为属性的类。

class Data(object):

    def __init__(self, array):
        self.array = array

    def remove_some(self, t):
        //operate on self.array
        pass

d = Data(z)
print(d.array)