2017-01-04 3 views
1

Dies ist mein Datenrahmen zählen:Reihen-Gruppe und mittlere berechnen und

df = 
UD QTY GRADE TIME_1 TIME_2 
1 20 5  22.5  16.1 
1 20 5  26.2  19.5 
1 20 5  30.0  14.0 
1 20 4  20.0  18.5 
2 25 4  23.3  19.9 

I Mittelwert von TIME_1 und TIME_2 für jede Kombination von UD und QTY berechnen müssen. Dann möchte ich die neue Spalte GRADE_COUNT hinzufügen, die die Gesamtzahl der Zeilen pro Gruppe speichert. Zum Beispiel setzen die in den oben angegebenen Daten sind 4 Zeilen pro Gruppe definiert durch UD = 1 und QTY = 20.

Das Ergebnis sollte sein, diese:

df = 

UD QTY MEAN_TIME_1 MEAN_TIME_2 COUNT 
1 20 24.67   17.02   4 
2 25 23.3   19.9   1 

ich diesen Code, welche Gruppen geschrieben Zeilen, berechnet Mittelwerte und zählt Werte.

groupby_object = df[['UD', 'QTY', 'GRADE', 'TIME_1', 'TIME_2']].groupby(['TIME_1', 'TIME_2]) 

df = groupby_object.agg('mean').rename(columns = lambda x: x + ' mean').join(pd.DataFrame(groupby_object.size(),columns=['counts'])).reset_index() 

Doch statt mittleren Zeiten der Berechnung, berechnet sie bedeuten QTY und GRADE, auch die Spalte UD verschwindet.

+0

'df.groupby ([ 'UD', 'Menge']) [[ 'TIME_1', 'TIME_2' ]].mean() '- ist das was du willst? – MaxU

+0

@MaxU: Bitte sehen Sie mein Update. Ich habe das erwartete Ergebnis veröffentlicht. – Dinosaurius

+0

@DavidZ: Ich benutze die letzte Version von Pandas: 0.19.1 – Dinosaurius

Antwort

4

Es ist möglich, alle verschiedenen Arten von Aggregationen in demselben Schritt ohne Zusammenführen oder Zuweisen durchzuführen. groupby.agg können Sie dies mit einem Wörterbuch von Spalten in die Aggregationsfunktion

df1 = df.groupby(['UD', 'QTY']).agg({'TIME_1': 'mean', 
            'TIME_2': 'mean', 
            'GRADE':'count'}).reset_index() 

    UD QTY TIME_1 GRADE TIME_2 
0 1 20 24.675  4 17.025 
1 2 25 23.300  1 19.900 
+0

Könnte die endgültige Lösung nur Zeilen enthalten, die ich als das erwartete Ergebnis in meiner Frage angegeben habe? – Dinosaurius

+2

Es sieht so aus, als ob Sie nur nach UD und QTY und nicht nach GRADE gruppieren. Ihr endgültiger Datenrahmen stimmt nicht mit dem überein, was Sie geschrieben haben –

+0

Ich habe meine Lösung auf etwas Einfaches aktualisiert –

1

Das Argument DataFrame.groupby() spezifiziert verwendet abgebildet tun, die Spalten verwendet werden soll Reihen in Gruppen zu kombinieren. Also, wenn Sie

df.groupby([['TIME_1', 'TIME_2']]) 

schreiben dann Pandas Reihen kombinieren, die die gleichen Werte von TIME_1 und TIME_2 haben. Aber Sie möchten Zeilen kombinieren, die die gleichen Werte von UD und QTY haben. (Wenn Sie auch zu Gruppenzeilen verwenden GRADE wollen, fügen Sie einfach, dass in gegebenenfalls.) So

>>> g = df.groupby([['UD', 'QTY']]) 

verwenden Dann können Sie einfach mean() auf der resultierende Objekt aufrufen, um die Mittel der Gruppen zu erhalten.

>>> g.mean() 
     GRADE TIME_1 TIME_2 
UD QTY      
1 20 4.75 24.675 17.025 
2 25 4.00 23.300 19.900 

Ebenso können Sie count() rufen Reihe zählt zu erhalten.

>>> g.count() 
     GRADE TIME_1 TIME_2 
UD QTY      
1 20  4  4  4 
2 25  1  1  1 

können Sie nun diese Stücke in eine neue DataFrame mit pandas.concat() montieren.

>>> m = g.mean() 
>>> c = g.count() 
>>> new_df = concat([m, c], axis=1) 
>>> new_df 
     TIME_1 TIME_2 GRADE 
UD QTY      
1 20 24.675 17.025  4 
2 25 23.300 19.900  1 

Was bleibt, ist UD und QTY von Indexspalten zu den regulären Spalten zu ändern, die Sie mit new_df.reset_index() tun können, und die Spaltennamen nach Ihren Wünschen ändern, die Sie durch die Zuweisung einer Liste new_df.columns tun können.

1

versuchen Sie dies:

In [295]: g = df.groupby(['UD','QTY'], as_index=False) 

In [297]: (pd.merge(g[['TIME_1','TIME_2']].mean(), 
    ...:   g.size().to_frame('COUNT').reset_index(), 
    ...:   on=['UD','QTY']) 
    ...:) 
    ...: 
Out[297]: 
    UD QTY TIME_1 TIME_2 COUNT 
0 1 20 24.675 17.025  4 
1 2 25 23.300 19.900  1 

oder etwas schöneres:

In [301]: g[['TIME_1','TIME_2']].mean().assign(COUNT=g.size().values) 
Out[301]: 
    UD QTY TIME_1 TIME_2 COUNT 
0 1 20 24.675 17.025  4 
1 2 25 23.300 19.900  1 
+0

Verstehe ich richtig, dass, wenn ich zum Beispiel keine Durchschnittszeiten berechnen muss, einfach 'g.assign (COUNT = g [['TIME_1', 'TIME_2']]. Size()) 'exclusive' [['TIME_1', 'TIME_2']]. mean() '? – Dinosaurius

+0

@Dinosaurus, ich würde versuchen, dies: 'g.size(). To_frame ('COUNT'). Reset_index()' – MaxU

+1

@Dinosaurus, sollten Sie wahrscheinlich markieren [Ted Lösung] (http://stackoverflow.com/a/ 41474022/5741205) als richtig - es ist viel besser und idiomatischer – MaxU

Verwandte Themen