10
votes

Problème de ndarray numpy de sous-classement

Je voudrais sous-classes Numpy Ndarray. Cependant, je ne peux pas changer le tableau. Pourquoi auto = ... code> ne change pas le tableau? Merci.

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 commentaires

Veuillez fournir votre production attendue, ce n'est pas clair ce que vous voulez réaliser.


Je veux supprimer les lignes de l'instance de données.


OK, vous pouvez utiliser un masque, mais mieux si vous posez une autre question car cela n'a pas grand-chose à voir avec le sous-classement Ndarray


[Une autre question a été postée] [1] avec le même problème lors de la sous-classement d'un ndarray . [1]: Stackoverflow.com/Questtions/16049437/...


3 Réponses :


6
votes

La raison pour laquelle vous ne recevez pas le résultat vous attendez est parce que vous êtes à nouveau attribuer auto dans la méthode supprimer_some . Vous créez simplement une nouvelle variable locale auto . Si votre forme de matrice ne devait pas changer, vous pouvez simplement faire vous-même [:] = ... et vous pouvez garder la référence à auto et tout irait bien, mais vous essayez de changer la forme de auto . Ce qui signifie que nous devons réaffecter une nouvelle mémoire et changer où nous indiquons lorsque nous nous référons lorsque nous nous référons à auto .

Je ne sais pas comment faire cela. Je pensais que cela pourrait être atteint par __ array_finalize __ ou __ tableau __ ou __ array_wrap __ . Mais tout ce que j'ai essayé est de tomber court.

Maintenant, il y a une autre façon d'y aller à ce sujet qui ne sousclure pas ndarray . Vous pouvez faire une nouvelle classe qui conserve un attribut qui est un ndarray, puis remplace tout le habituel __ ajouter __ , __ mul __ , etc .. quelque chose comme ceci: < Pré> xxx

Eh bien, vous obtenez la photo. C'est une douleur à remplacer tous les opérateurs, mais à long terme, je pense plus flexible.

vous devrez lire Ceci à fond pour le faire correctement. Il existe des méthodes telles que __ array_finalize __ qui doivent être appelés le bon moment pour faire "nettoyage".


2 commentaires

Je pensais que __ Array_Finalize __ est utilisé lors de l'initiative d'une nouvelle instance, par exemple dans l'ajout d'attributs supplémentaires.


Je pensais que cela devait être appelé à tout moment, vous réaffectaez le tableau comme le faire. Mais pour être honnête, c'est sur ma tête. __ Array_wrap __ semble être plus proche de ce qui est recherché, mais ne revient que lorsqu'il est appelé par un ufunc.



3
votes

J'ai essayé de faire de même, mais c'est vraiment très complexe de sous-classe Ndarray.

Si vous devez ajouter certaines fonctionnalités, je suggérerais de créer une classe qui stocke la matrice en tant qu'attribut. xxx


1 commentaires

Documentation sur la section Sub Class NDARRAY pourrait aider à faciliter la tâche .



5
votes

peut-être faire une fonction, plutôt qu'une méthode: xxx pré>


ou, si vous le souhaitez comme méthode, P>

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)


3 commentaires

C'est peut-être une réponse utile à la question, mais n'est pas une réponse. Pourquoi Self = ... ne change pas la valeur? Peut-être que la réponse est ci-dessous? Je republai autrement.


Imaginez d , votre instance . Il pointe vers un bloc de mémoire qui détient les données sous-jacentes. Pour supprimer une colonne in-place , vous devez déplacer les autres colonnes ensemble, puis redimensionner la matrice. Lorsque vous dites self = quelque_other_array Vous redirigez le nom de la variable auto dans un autre bloc de mémoire. En dehors de la méthode supprimer_row , cependant, le nom de la variable d est toujours pointé vers le bloc de mémoire d'origine. Donc, il ne modifie pas d .


Tous les conseils que j'ai jamais lus à propos de NUMPY DIREL indique, il ne faut pas essayer de redimensionner des tableaux numpopiques. Il est possible de faire, mais tout la copie le rend lent. Il est préférable d'utiliser des tranches pour créer des vues ou une indexation fantaisie pour créer de nouveaux tableaux avec les données souhaitées. Oui, faire une nouvelle matrice implique également de copier, mais au moins vous êtes sauvegardé de la complexité des données changeantes autour de la place.