Numpy: python3: Regression für Unique on dtype = Objektarrays mit unterschiedlichen Elementtypen (Trac # 2188)

Erstellt am 19. Okt. 2012  ·  18Kommentare  ·  Quelle: numpy/numpy

_Ursprüngliches Ticket http://projects.scipy.org/numpy/ticket/2188 am 23.07.2012 von @yarikoptic , zugewiesen an unknown._

getestet gegen den aktuellen Master (auch in 1.6.2 vorhanden):

Wenn es mit der python2.x-Serie funktioniert, ohne zu kotzen:

$> python2.7 -c 'import numpy as np; print repr(repr(np.unique(np.array([1,2, None, "str"]))))' 
'array([None, 1, 2, str], dtype=object)'

NB Ich werde einen Fehler bei Repr hier separat melden, wenn er noch nicht eingereicht wurde

es schlägt mit python3.x insgesamt fehl:

$> python3.2 -c 'import numpy as np; print(repr(repr(np.unique(np.array([1,2,None, "str"])))))'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/local/lib/python3.2/dist-packages/numpy/lib/arraysetops.py", line 194, in unique
    ar.sort()
TypeError: unorderable types: int() > NoneType()

Wann immer IMHO es korrekt funktionieren muss - die Semantik von unique () action sollte nicht die Fähigkeit implizieren, die Elemente zu sortieren

00 - Bug numpy.core

Hilfreichster Kommentar

Irgendwelche Updates dazu? Ich bin auf diesen Fehler gestoßen, als ich versucht habe, den LabelEncoder von scikit-learn für Pandas-DataFrame-Spalten mit dem Typ "Objekt" und fehlenden Werten zu verwenden

Alle 18 Kommentare

irgendwelche neuen Ideen zu diesem Thema?

Die einzigen Optionen zum Implementieren von unique sind:

  • Sortieren des Arrays
  • alles in eine Hash-Tabelle legen
  • Führen Sie einen Brute-Force-Vergleich von == für alle Objekte mit allen Objekten durch

Nur die Sortier- und Hashing-Strategien haben eine angemessene Geschwindigkeit, und nur die Sortier- und All-gegen-Alles-Strategien haben einen angemessenen Speicheraufwand für große Arrays. Ich denke also, wir könnten Unique Fallback-Optionen hinzufügen. Wenn das Sortieren nicht funktioniert, wird eine der anderen Strategien ausprobiert. Aber OTOH, es ist nicht schön, eine Funktion zu haben, die manchmal plötzlich massiv mehr CPU oder Speicher benötigt, je nachdem, welchen Eingang Sie geben.

Ich denke, ich würde +1 für einen Patch sein, der np.unique eine Option option = {"sort", "hash", "bruteforce"} hinzufügt, damit Benutzer mit seltsamen Daten entscheiden können, was für ihre Situation sinnvoll ist. Wenn du so etwas schreiben willst :-)

Zuerst habe ich mich gefragt, ob es sich um eine Sortierung + Hash-Tabelle für unsortierbare Elemente handeln könnte (ich habe nicht überprüft, ob beim Sortieren von Elementen des dtype-Objektarrays cmp von Elementen verwendet wird), sodass das Sortieren von __cmp__ sie auf "first come" positionieren könnte -first-in-line 'Bestellung?
aber dann wurde mir klar, dass es für unvergleichliche Typen im Allgemeinen keine Erleichterung darstellt, z. B. wenn es sich um eine Mischung aus int und str handelt ... also fragte ich mich, ob es für dtype = object möglich sein könnte, zuerst teilnehmende dtypes und 'unique abzuleiten '(möglicherweise über sort) innerhalb jedes dtype möglicherweise unter Verwendung von Hash-Tabellen für dtypes ohne __cmp__ ?

Nur für diejenigen, die eine Problemumgehung benötigen, ist hier, wie ich es durch 'Hashing' durch die eingebauten Sets für meinen Fall mache:

$> python3.3 -c 'import numpy as np; print(np.array(list(set([1,2,"str", None])), dtype=object))' 
[None 1 2 'str']

Ich bin mir nicht sicher, was du gerade gesagt hast :-)

Aber bei weiteren Überlegungen ist die Sortierung für dtype = object wirklich nicht zuverlässig
wie auch immer. Ich habe wahrscheinlich Dutzende von Klassen geschrieben, die Gl. Aber überschreiben
Behalten Sie die Standardeinstellung lt bei , was bedeutet, dass sort-based unique nur wird
Geben Sie stillschweigend die falsche Antwort zurück. Dies ist ein ziemlich böser Fehler, denke ich.

Wenn die Objekte hashbar sind, können Sie einfach set (arr) ausführen, um das Unique zu erhalten
Elemente, aber keine Garantie, dass sie im Allgemeinen hashbar sind. (Aber wenigstens
Jeder, der dies für hashbare Objekte tut, sollte funktionieren, was nicht wahr ist
zum Sortieren.) Vielleicht wäre dies eine bessere Standardimplementierung von
np.unique für Objektarrays.

Am Dienstag, 17. September 2013, um 17:40 Uhr, Yaroslav Halchenko <
[email protected]> schrieb:

Zuerst habe ich mich gefragt, ob es eine Sortierung + Hash-Tabelle für unsortierbar sein könnte
items (hat nicht überprüft, ob _cmp_ von Elementen beim Sortieren von Elementen von verwendet wird
dtype object array), damit das Sortieren von cmp sie positionieren kann
'first-come-first-in-line'-Bestellung?
aber dann wurde klar, dass es im Allgemeinen keine Erleichterung für
unvergleichliche Typen, zB wenn es eine Mischung aus int und str ist ... also habe ich mich gefragt
Wenn für dtype = object eine erste Teilnahme möglich ist
dtypes und 'unique' (möglicherweise über sort) innerhalb jedes dtype möglicherweise abhängig
auf Hash-Tabellen für dtypes ohne cmp ?

- -
Antworten Sie direkt auf diese E-Mail oder sehen Sie sie sich auf Gi tHubhttps an: //github.com/numpy/numpy/issues/641#issuecomment -24603047
.

gy ... ok - grausame Beschreibung in Python:

def bucketed_unique(a):
    buckets = {}
    for x in a:
        t = type(x)
        if not (t in buckets):
            buckets[t] = bucket = []
        else:
            bucket = buckets[t]
        bucket.append(x)
    out = []
    for bucket in buckets.itervalues():
        # here could be actually set of conditions instead of blind try/except
        try:
            out.append(np.unique(bucket))
        except:
            out.append(np.array(list(set(bucket)), dtype=object))
    return np.hstack(out)
print bucketed_unique([1, 2, 'str', None, np.nan, None, np.inf, int])
[1 2 'str' None <type 'int'> nan inf]

Sicher - für Nicht-Objekt-Ndarrays sollte kein "Bucketing" durchgeführt werden

Dieser Algorithmus verwendet == nicht als Definition der Eindeutigkeit. Objekte von
verschiedene Typen können == sein. (Einfaches Beispiel: 1, 1.0). Seine Definition tut es nicht
entsprechen jedem Standard-Python-Konzept.
Am 17. September 2013 um 18:01 Uhr schrieb "Yaroslav Halchenko" [email protected] :

Sicher - für Nicht-Objekt-Ndarrays sollte kein "Bucketing" durchgeführt werden

- -
Antworten Sie direkt auf diese E-Mail oder sehen Sie sie sich auf Gi tHubhttps an: //github.com/numpy/numpy/issues/641#issuecomment -24604740
.

tatsächlich! Ich bin mir nicht sicher, aber möglicherweise ist eine Post-hoc-Analyse über mehrere Eimer hinweg sinnvoll. Übrigens zeigt sich das Problem auch beim Vergleich mit komplexen Zahlen:

$> python3.3 -c 'import numpy as np; print(np.unique(np.array([1, 1.0, 1+0j], dtype=object)))'  
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/numpy/lib/arraysetops.py", line 194, in unique
    ar.sort()
TypeError: unorderable types: float() > complex()

$> python -c 'import numpy as np; print(np.unique(np.array([1, 1.0, 1+0j], dtype=object)))' 
[1]

obwohl beim zweiten Gedanken - was sollte der 'eindeutige' Wert dtype dann unter allen verfügbaren Auswahlmöglichkeiten sein (int / float / complex)? bei Nicht-Objekt-Arrays ist es klar ... bei heterogenen Objekt-Arrays nicht so - möglicherweise sollten sogar verschiedene d-Typen als solche beibehalten werden ...

Hier ist die Art und Weise, wie ich argsort gelöst habe, die in py3 auf gemischtem int / str explodiert sind: https://github.com/pydata/pandas/pull/6222/files

Ordne die Ints vor den Strings in Objekt-D-Typen
Verwenden Sie eine Hashtabelle, um die Positionen zuzuordnen, an denen der Indexer abgerufen werden soll
ziemlich schnell denke ich

Verwendet die Pandas-Hashtable-Implementierung, könnte aber meiner Meinung nach leicht ausgetauscht / an C-Code angepasst werden

Möchte jemand einen Schwung nehmen? Ich bin mir nicht sicher, was ich mit Datensatztypen tun soll.

Irgendwelche Updates dazu? Ich bin auf diesen Fehler gestoßen, als ich versucht habe, den LabelEncoder von scikit-learn für Pandas-DataFrame-Spalten mit dem Typ "Objekt" und fehlenden Werten zu verwenden

Dieser ist wirklich alt. Ist es immer noch relevant?

scheint zumindest bei 1.15.4 in debian der Fall zu sein:

$> python3 --version
Python 3.6.5

$> PYTHONPATH=.. python3 -c 'import numpy as np; print(np.__version__); print(repr(repr(np.unique(np.array([1,2,None, "str"])))))'                                                                                   
1.15.4
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/numpy/lib/arraysetops.py", line 233, in unique
    ret = _unique1d(ar, return_index, return_inverse, return_counts)
  File "/usr/lib/python3/dist-packages/numpy/lib/arraysetops.py", line 281, in _unique1d
    ar.sort()
TypeError: '<' not supported between instances of 'NoneType' and 'int'

Auf jeden Fall noch relevant. Ich bin gerade darauf gestoßen und habe versucht, np.unique(x, return_inverse=True) für ein Objektarray aufzurufen.

In Bezug auf die Frage, wie dies funktioniert, wenn die Sortierung undefiniert ist: Ich würde einen langsamen Algorithmus dem Status Quo des Auslösens eines Fehlers vorziehen. (Nach meiner Erfahrung sollten Sie häufig kein Objektarray verwenden, wenn Sie performante Algorithmen benötigen.)

Ich denke, dies ist eine Feature-Anfrage, kein Fehler. In den Dokumenten heißt es eindeutig:

Gibt die _sortierten_ eindeutigen Elemente eines Arrays zurück.

Für den Fall eines Arrays wie [1, None] gibt es in Python 3 kein solches sortiertes Array, da die Sortierung nicht mehr genau definiert ist.

Es wäre schön, eine Option zu haben, um ein sortiertes Array nicht zurückzugeben, es würde einige Optimierungen ermöglichen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen