Es fällt mir schwer, ein Problem zu debuggen, bei dem der Float nan
in a list
und nan
in a numpy.array
unterschiedlich behandelt wird, wenn diese verwendet werden in itertools.groupby
:
Angesichts der folgenden Liste und Array:
from itertools import groupby
import numpy as np
lst = [np.nan, np.nan, np.nan, 0.16, 1, 0.16, 0.9999, 0.0001, 0.16, 0.101, np.nan, 0.16]
arr = np.array(lst)
Wenn ich die Liste durchlaufe, werden die zusammenhängenden nan
s gruppiert:
>>> for key, group in groupby(lst):
... if np.isnan(key):
... print(key, list(group), type(key))
nan [nan, nan, nan] <class 'float'>
nan [nan] <class 'float'>
Wenn ich das Array jedoch verwende, werden aufeinanderfolgende nan
s in verschiedene Gruppen eingeteilt:
>>> for key, group in groupby(arr):
... if np.isnan(key):
... print(key, list(group), type(key))
nan [nan] <class 'numpy.float64'>
nan [nan] <class 'numpy.float64'>
nan [nan] <class 'numpy.float64'>
nan [nan] <class 'numpy.float64'>
Auch wenn ich das Array wieder in eine Liste konvertiere:
>>> for key, group in groupby(arr.tolist()):
... if np.isnan(key):
... print(key, list(group), type(key))
nan [nan] <class 'float'>
nan [nan] <class 'float'>
nan [nan] <class 'float'>
nan [nan] <class 'float'>
Ich benutze:
numpy 1.11.3
python 3.5
Ich weiß das im Allgemeinen. nan != nan
Warum führen diese Operationen zu unterschiedlichen Ergebnissen? Und wie ist es möglich, dass groupby
Gruppen überhaupt gruppiert werden nan
können?
Python-Listen sind nur Arrays von Zeigern auf Objekte im Speicher. Insbesondere lst
enthält Zeiger auf das Objekt np.nan
:
>>> [id(x) for x in lst]
[139832272211880, # nan
139832272211880, # nan
139832272211880, # nan
139832133974296,
139832270325408,
139832133974296,
139832133974464,
139832133974320,
139832133974296,
139832133974440,
139832272211880, # nan
139832133974296]
( np.nan
ist bei 139832272211880 auf meinem Computer.)
Andererseits sind NumPy-Arrays nur zusammenhängende Speicherbereiche. Dies sind Bereiche von Bits und Bytes, die von NumPy als eine Folge von Werten (Floats, Ints usw.) interpretiert werden.
Das for
Problem ist groupby
, dass Python diese Bytes in ein geeignetes Python-Objekt packen muss , wenn Sie Python auffordern, über ein NumPy-Array mit schwebenden Werten (auf einer Schleife oder Ebene) zu iterieren . Es erstellt ein brandneues Python-Objekt im Speicher für jeden einzelnen Wert im Array, während es iteriert.
Sie können beispielsweise sehen, dass für jeden nan
Wert unterschiedliche Objekte erstellt werden, wenn .tolist()
Folgendes aufgerufen wird:
>>> [id(x) for x in arr.tolist()]
[4355054616, # nan
4355054640, # nan
4355054664, # nan
4355054688,
4355054712,
4355054736,
4355054760,
4355054784,
4355054808,
4355054832,
4355054856, # nan
4355054880]
itertools.groupby
kann np.nan
für die Python-Liste gruppiert werden, da beim Vergleich von Python-Objekten zuerst die Identität überprüft wird . Da diese Zeiger auf nan
alle auf dasselbe np.nan
Objekt zeigen, ist eine Gruppierung möglich.
Die Iteration über das NumPy-Array ermöglicht jedoch nicht, dass diese anfängliche Identitätsprüfung erfolgreich ist. Daher greift Python auf die Überprüfung der Gleichheit zurück, nan != nan
wie Sie sagen.
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen