Subclasificando un problema de ndarray numpy

Me gustaría subclase numpy ndarray. Sin embargo, no puedo cambiar la matriz. ¿Por qué self = ... no cambia la matriz? Gracias.

 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? 

Quizás haga de esto una función, en lugar de un método:

 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', ' 

O, si lo quieres como método,

 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) 

La diferencia clave aquí es que remove_some no intenta modificarse a self , simplemente devuelve una nueva instancia de Data .

La razón por la que no obtiene el resultado que espera es porque se está reasignando a self dentro del método remove_some . Sólo estás creando una nueva variable local self . Si la forma de su matriz no cambiara, simplemente podría hacer self [:] = … y podría mantener la referencia a self y todo estaría bien, pero está intentando cambiar la forma de self . Lo que significa que debemos reasignar una nueva memoria y cambiar a dónde apuntamos cuando nos referimos a self .

No se como hacer esto. Pensé que podría lograrse con __array_finalize__ o __array__ o __array_wrap__ . Pero todo lo que he intentado se está quedando corto.

Ahora, hay otra manera de hacer esto que no hace una subclase de ndarray . Puede crear una nueva clase que mantenga un atributo que sea un ndarray y luego anular todos los habituales __add__ , __mul__ , etc. Algo así:

 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) 

Bueno, te haces una idea. Es un dolor anular a todos los operadores, pero a la larga, creo que es más flexible.

Tendrás que leer esto detenidamente para hacerlo bien. Hay métodos como __array_finalize__ que deben llamarse el momento adecuado para hacer “limpieza”.

Intenté hacer lo mismo, pero es realmente muy complejo para la subclase ndarray.

Si solo tiene que agregar alguna funcionalidad, sugeriría crear una clase que almacene la matriz como atributo.

 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)