Wenn Sie die Speicherkosten für die Konvertierung in eine Reihe von Tupeln oder eine andere ähnliche Datenstruktur vermeiden möchten, können Sie die strukturierten Arrays von numpy nutzen.
Der Trick besteht darin, Ihr ursprüngliches Array als strukturiertes Array anzuzeigen, wobei jedes Element einer Zeile des ursprünglichen Arrays entspricht. Dies macht keine Kopie und ist sehr effizient.
Als schnelles Beispiel:
import numpy as np
data = np.array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
ncols = data.shape[1]
dtype = data.dtype.descr * ncols
struct = data.view(dtype)
uniq = np.unique(struct)
uniq = uniq.view(data.dtype).reshape(-1, ncols)
print uniq
Schauen Sie sich die Zwischenergebnisse an, um zu verstehen, was los ist.
Sobald wir die Dinge als strukturiertes Array betrachten, ist jedes Element im Array eine Zeile in Ihrem ursprünglichen Array. (Grundsätzlich ist es eine ähnliche Datenstruktur wie eine Liste von Tupeln.)
In [71]: struct
Out[71]:
array([[(1, 1, 1, 0, 0, 0)],
[(0, 1, 1, 1, 0, 0)],
[(0, 1, 1, 1, 0, 0)],
[(1, 1, 1, 0, 0, 0)],
[(1, 1, 1, 1, 1, 0)]],
dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])
In [72]: struct[0]
Out[72]:
array([(1, 1, 1, 0, 0, 0)],
dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])
Sobald wir ausgeführt werden numpy.unique
, erhalten wir ein strukturiertes Array zurück:
In [73]: np.unique(struct)
Out[73]:
array([(0, 1, 1, 1, 0, 0), (1, 1, 1, 0, 0, 0), (1, 1, 1, 1, 1, 0)],
dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])
Das müssen wir dann als "normales" Array anzeigen ( _
speichert das Ergebnis der letzten Berechnung in ipython
, weshalb Sie sehen _.view...
):
In [74]: _.view(data.dtype)
Out[74]: array([0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0])
Und dann wieder in ein 2D-Array umformen ( -1
ist ein Platzhalter, der numpy anweist, die richtige Anzahl von Zeilen zu berechnen und die Anzahl der Spalten anzugeben):
In [75]: _.reshape(-1, ncols)
Out[75]:
array([[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
Wenn Sie präziser sein möchten, können Sie dies natürlich wie folgt schreiben:
import numpy as np
def unique_rows(data):
uniq = np.unique(data.view(data.dtype.descr * data.shape[1]))
return uniq.view(data.dtype).reshape(-1, data.shape[1])
data = np.array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
print unique_rows(data)
Was in ... endet:
[[0 1 1 1 0 0]
[1 1 1 0 0 0]
[1 1 1 1 1 0]]