web-dev-qa-db-de.com

Gibt es eine numpy Gruppe nach Funktion?

Gibt es eine Funktion in numpy, um dieses Array unten in der ersten Spalte zu gruppieren?

Ich konnte keine gute Antwort über das Internet finden ..

>>> a
array([[  1, 275],
       [  1, 441],
       [  1, 494],
       [  1, 593],
       [  2, 679],
       [  2, 533],
       [  2, 686],
       [  3, 559],
       [  3, 219],
       [  3, 455],
       [  4, 605],
       [  4, 468],
       [  4, 692],
       [  4, 613]])

Gewünschte Ausgabe:

array([[[275, 441, 494, 593]],
       [[679, 533, 686]],
       [[559, 219, 455]],
       [[605, 468, 692, 613]]], dtype=object)
19
John Dow

Inspiriert von Eelco Hoogendoorns Bibliothek, jedoch ohne seine Bibliothek, und die Tatsache, dass die erste Spalte Ihres Arrays immer größer wird.

>>> np.split(a[:, 1], np.cumsum(np.unique(a[:, 0], return_counts=True)[1])[:-1])
[array([275, 441, 494, 593]),
 array([679, 533, 686]),
 array([559, 219, 455]),
 array([605, 468, 692, 613])]

Ich habe nicht "Timeit", aber dies ist wahrscheinlich der schnellere Weg, um die Frage zu erreichen:

  • Keine native Python-Schleife
  • Ergebnislisten sind numpy-Arrays. Falls Sie weitere numpy-Vorgänge für sie durchführen müssen, ist keine neue Konvertierung erforderlich
  • Komplexität wie O (n)

PS: Ich habe eine ähnliche Zeile geschrieben, weil ich die Ergebnisse von np.nonzero "gruppieren" musste:

>>> indexes, values = np.nonzero(...)
>>> np.split(values, np.cumsum(np.unique(indexes, return_counts=True)[1]))
12
Vincent J

Das Paket numpy_indexed (Disclaimer: Ich bin sein Autor) soll diese Lücke in numpy schließen. Alle Operationen in numpy-indexed sind vollständig vektorisiert, und bei der Erstellung dieser Bibliothek wurden keine O (n ^ 2) -Algorithmen beschädigt.

import numpy_indexed as npi
npi.group_by(a[:, 0]).split(a[:, 1])

Beachten Sie, dass es normalerweise effizienter ist, relevante Eigenschaften direkt über solche Gruppen zu berechnen (z. B. group_by (keys) .mean (values)), anstatt sie zuerst in ein list/jagged-Array zu teilen.

7

Numpy ist hier nicht sehr praktisch, da die gewünschte Ausgabe kein Array von Ganzzahlen ist (es ist ein Array von Listenobjekten).

Ich empfehle entweder die reine Python-Methode ...

from collections import defaultdict

%%timeit
d = defaultdict(list)
for key, val in a:
    d[key].append(val)
10.7 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# result:
defaultdict(list,
        {1: [275, 441, 494, 593],
         2: [679, 533, 686],
         3: [559, 219, 455],
         4: [605, 468, 692, 613]})

... oder der Pandas Weg:

import pandas as pd

%%timeit
df = pd.DataFrame(a, columns=["key", "val"])
df.groupby("key").val.apply(pd.Series.tolist)
979 µs ± 3.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# result:
key
1    [275, 441, 494, 593]
2         [679, 533, 686]
3         [559, 219, 455]
4    [605, 468, 692, 613]
Name: val, dtype: object
5
Piotr
n = unique(a[:,0])
array( [ list(a[a[:,0]==i,1]) for i in n] )

ausgänge:

array([[275, 441, 494, 593], [679, 533, 686], [559, 219, 455],
       [605, 468, 692, 613]], dtype=object)
4
Gioelelm

Vereinfachung der Antwort von Vincent J one kann return_index = True anstelle von return_counts = True verwenden und die cumsum entfernen

np.split(a[:,1], np.unique(idx,return_index = True)[1][1:])

Ausgabe

[array([275, 441, 494, 593]),
 array([679, 533, 686]),
 array([559, 219, 455]),
 array([605, 468, 692, 613])]
3
ns63sr

wenn Sie X als Array von Elementen angeben, die Sie gruppieren möchten, und Y (1D-Array) als entsprechende Gruppen, führt die folgende Funktion die Gruppierung mit numpy durch:

def groupby(X, y):
    y = np.asarray(y)
    X = np.asarray(X)
    y_uniques = np.unique(y)
    return [X[y==yi] for yi in y_uniques]

Also gibt groupby(a[:,1], a[:,0])[array([275, 441, 494, 593]), array([679, 533, 686]), array([559, 219, 455]), array([605, 468, 692, 613])] zurück

0
Guido Mocha

Ich habe np.unique () gefolgt von np.extract () verwendet

unique = np.unique(a[:, 0:1])
answer = []
for element in unique:
    present = a[:,0]==element
    answer.append(np.extract(present,a[:,-1]))
print (answer)

[array([275, 441, 494, 593]), array([679, 533, 686]), array([559, 219, 455]), array([605, 468, 692, 613])]

0
user2251346