子类numpy ndarray问题

riz*_*iza 9 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?
Run Code Online (Sandbox Code Playgroud)

Pau*_*aul 6

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

我不知道该怎么做.我认为它可以通过__array_finalize____array__或实现__array_wrap__.但我所尝试的一切都不尽如人意.

现在,还有另一种方法可以解决这个问题ndarray.你可以,它可将是一个ndarray和属性的新类,然后覆盖所有常见的__add__,__mul__等等.事情是这样的:

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)
Run Code Online (Sandbox Code Playgroud)

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

你必须阅读彻底把事情做对.有类似的方法 __array_finalize__需要被称为进行"清理"的正确时间.


unu*_*tbu 5

也许使它成为一个函数,而不是一个方法:

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')])
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

这里的关键区别在于remove_some不尝试修改self,它仅返回 的新实例Data