2014-03-06 8 views
67

ich einen Pandas Datenrahmen haben wie:Gruppierung Zeilen in der Liste in Pandas GROUPBY

A 1 
A 2 
B 5 
B 5 
B 4 
C 6 

ich von der ersten Spalte gruppiert werden sollen und die zweite Spalte als Listen in Reihen erhalten:

A [1,2] 
B [5,5,4] 
C [6] 

Ist ist es möglich, so etwas mit pandas groupby zu tun?

+1

Das Speichern von Listen in Datenrahmen ist ineffizient, warum möchten Sie das tun? – EdChum

+1

Liste ist ein Beispiel, könnte alles sein, wo ich auf alle Einträge aus der gleichen Gruppe in einer Zeile zugreifen kann –

+0

Ich denke, wenn Sie nur nach den Spalten gruppiert und Zugriff auf die Daten für diese Gruppe dann spart es, eine Liste zu generieren, was wird zurückgegeben wird ein Pandas Datenrahmen/Serie für diese Gruppe – EdChum

Antwort

106

Sie können dies auf der Säule von Interesse groupby zu einer Gruppe mit tun und apply dann list zu jeder Gruppe:

In [1]: 
# create the dataframe  
df = pd.DataFrame({'a':['A','A','B','B','B','C'], 'b':[1,2,5,5,4,6]}) 
df 
Out[1]: 
    a b 
0 A 1 
1 A 2 
2 B 5 
3 B 5 
4 B 4 
5 C 6 

[6 rows x 2 columns] 

In [76]: 
df.groupby('a')['b'].apply(list) 

Out[76]: 
a 
A  [1, 2] 
B [5, 5, 4] 
C   [6] 
Name: b, dtype: object 
+3

Dies dauert eine Menge Zeit, wenn der Datensatz riesig ist, sagen 10 Millionen Zeilen. Gibt es einen schnelleren Weg, dies zu tun? Die Anzahl der Uniques in 'a' ist jedoch um 500k –

+3

groupby ist notorisch langsam und Speicher hungrig, was Sie tun könnten, ist nach Spalte A, dann finden Sie die idxmin und idxmax (wahrscheinlich speichern Sie dies in einem Diktat) und verwenden Sie dies zu schneiden Ihr Dataframe würde schneller sein Ich denke, – EdChum

+0

@AbhishekThakur tatsächlich wird das nicht funktionieren, da 'idxmin' nicht für Strings funktioniert, müssten Sie die Anfangs- und Endindexwerte speichern – EdChum

7

Wie Sie sagten, die groupby Methode eines pd.DataFrame Objekts kann den Job erledigen.

Beispiel

L = ['A','A','B','B','B','C'] 
N = [1,2,5,5,4,6] 

import pandas as pd 
df = pd.DataFrame(zip(L,N),columns = list('LN')) 


groups = df.groupby(df.L) 

groups.groups 
     {'A': [0, 1], 'B': [2, 3, 4], 'C': [5]} 

die und index weise Beschreibung der Gruppen gibt.

Um Elemente der einzelnen Gruppen zu erhalten, die Sie tun können, zum Beispiel

groups.get_group('A') 

    L N 
    0 A 1 
    1 A 2 

    groups.get_group('B') 

    L N 
    2 B 5 
    3 B 5 
    4 B 4 
13

Wenn die Leistung wichtig ist numpy Ebene nach unten gehen:

import numpy as np 

df = pd.DataFrame({'a':np.random.randint(0,60,600), 'b':[1,2,5,5,4,6]*100}) 

def f(df): 
     keys,values=df.sort_values('a').values.T 
     ukeys,index=np.unique(keys,True) 
     arrays=np.split(values,index[1:]) 
     df2=pd.DataFrame({'a':ukeys,'b':[list(a) for a in arrays]}) 
     return df2 

Tests:

In [301]: %timeit f(df) 
1000 loops, best of 3: 1.64 ms per loop 

In [302]: %timeit df.groupby('a')['b'].apply(list) 
100 loops, best of 3: 5.26 ms per loop