2017-10-18 2 views
1

ich Pandas Datenrahmen haben, die etwa wie folgt aussieht:Erhalten Reihenfolge der Untergruppen in Pandas Datenrahmen

df = pd.DataFrame({'Name' : ['Kate', 'John', 'Peter','Kate', 'John', 'Peter'],'Distance' : [23,16,32,15,31,26], 'Time' : [3,5,2,7,9,4]}) 
df 


    Distance Name Time 
0 23  Kate 3 
1 16  John 5 
2 32  Peter 2 
3 15  Kate 7 
4 31  John 9 
5 26  Peter 2 

Ich möchte eine Spalte hinzufügen, die mir sagt, für jeden Namen, was ist die Reihenfolge der Zeit.

Ich möchte etwas wie folgt aus:

Order Distance Name Time 
    0  16  John 5 
    1  31  John 9 
    0  23  Kate 3 
    1  15  Kate 7 
    0  32  Peter 2 
    1  26  Peter 4 

Ich kann es eine for-Schleife tun mit:

df2 = df[df['Name'] == 'aaa'].reset_index().reset_index() # I did this just to create an empty data frame with the columns I want 

for name, row in df.groupby('Name').count().iterrows(): 
    table = df[df['Name'] == name].sort_values('Time').reset_index().reset_index() 
    to_concat = [df2,table] 
    df2 = pd.concat(to_concat) 

df2.drop('index', axis = 1, inplace = True) 
df2.columns = ['Order', 'Distance', 'Name', 'Time'] 
df2 

Dies funktioniert, das Problem ist (abgesehen von sehr unpythonic ist), für große Tabellen (meine tatsächliche Tabelle hat etwa 50 Tausend Zeilen) es dauert etwa eine halbe Stunde zu laufen.

Kann jemand mir helfen, dies auf eine einfachere Weise zu schreiben, die schneller läuft? Es tut mir leid, wenn das irgendwo beantwortet wurde, aber ich wusste nicht wirklich, wie man danach sucht.

Best,

Antwort

2

Verwenden sort_values mit cumcount:

df = df.sort_values(['Name','Time']) 
df['Order'] = df.groupby('Name').cumcount() 
print (df) 

    Distance Name Time Order 
1  16 John  5  0 
4  31 John  9  1 
0  23 Kate  3  0 
3  15 Kate  7  1 
2  32 Peter  2  0 
5  26 Peter  4  1 

Wenn Bedarf zuerst Säulenbenutzung insert:

df = df.sort_values(['Name','Time']) 
df.insert(0, 'Order', df.groupby('Name').cumcount()) 
print (df) 
    Order Distance Name Time 
1  0  16 John  5 
4  1  31 John  9 
0  0  23 Kate  3 
3  1  15 Kate  7 
2  0  32 Peter  2 
5  1  26 Peter  4 
1
In [67]: df = df.sort_values(['Name','Time']) \ 
       .assign(Order=df.groupby('Name').cumcount()) 

In [68]: df 
Out[68]: 
    Distance Name Time Order 
1  16 John  5  0 
4  31 John  9  1 
0  23 Kate  3  0 
3  15 Kate  7  1 
2  32 Peter  2  0 
5  26 Peter  4  1 

PS Ich bin nicht sicher, dies die eleganteste Art und Weise, dies zu tun ...

+0

Aus irgendeinem Grund funktioniert das nicht ganz, für einige Namensgruppen startet die "Order" auf halbem Wege neu. Zum Beispiel für Reihen mit dem gleichen Namen bekam ich Aufträge wie 0,1,2,0,1. Jezraels Antwort funktioniert aber. – user5576

Verwandte Themen