11

numpyndarrayをサブクラス化したいと思います。ただし、配列を変更することはできません。なぜ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?
4

3 に答える 3

6

self期待した結果が得られない理由は、メソッド内で再割り当てを行っているためですremove_some。新しいローカル変数を作成しているだけですself。配列の形状が変更されない場合は、単純に 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)

さて、あなたは絵を手に入れます。すべての演算子をオーバーライドするのは面倒ですが、長い目で見れば、より柔軟になると思います。

これを正しく行うには、これをよく読む必要があります。__array_finalize__「クリーンアップ」を行う適切なタイミングで呼び出される必要があるようなメソッドがあります 。

于 2011-03-01T00:56:48.897 に答える
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')])

または、メソッドとして使用する場合は、

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

于 2011-03-01T13:05:38.747 に答える
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)
于 2011-03-01T02:12:50.727 に答える