簡體   English   中英

子類numpy ndarray問題

[英]Subclassing numpy ndarray problem

我想繼承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?

您沒有得到預期結果的原因是因為您在方法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__這樣的方法需要被稱為正確的“清理”時間。

也許這是一個函數,而不是一個方法:

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實例。

我嘗試做同樣的事情,但是將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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM