Es wird versucht, eine neue Spalte aus der groupby
Berechnung zu erstellen . Im folgenden Code erhalte ich die korrekt berechneten Werte für jedes Datum (siehe Gruppe unten), aber wenn ich versuche, eine neue Spalte ( df['Data4']
) damit zu erstellen, erhalte ich NaN. Ich versuche also, eine neue Spalte im Datenrahmen mit der Summe Data3
aller Daten zu erstellen und diese auf jede Datumszeile anzuwenden. Zum Beispiel ist der 08.05.2015 in 2 Zeilen (insgesamt 50 + 5 = 55) und in dieser neuen Spalte möchte ich 55 in beiden Zeilen haben.
import pandas as pd
import numpy as np
from pandas import DataFrame
df = pd.DataFrame({
'Date' : ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'],
'Sym' : ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'],
'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
'Data3': [5, 8, 6, 1, 50, 100, 60, 120]
})
group = df['Data3'].groupby(df['Date']).sum()
df['Data4'] = group
python
pandas
group-by
pandas-groupby
zB ner
quelle
quelle
df.groupby('Date')['Data3'].transform('sum')
(was ich etwas leichter zu merken finde).Es gibt zwei Möglichkeiten - eine einfache und eine etwas interessantere.
Jedermanns Favorit:
GroupBy.transform()
mit'sum'
Die Antwort von @Ed Chum kann ein wenig vereinfacht werden. Rufen Sie
DataFrame.groupby
lieber an alsSeries.groupby
. Dies führt zu einer einfacheren Syntax.# The setup. df[['Date', 'Data3']] Date Data3 0 2015-05-08 5 1 2015-05-07 8 2 2015-05-06 6 3 2015-05-05 1 4 2015-05-08 50 5 2015-05-07 100 6 2015-05-06 60 7 2015-05-05 120
df.groupby('Date')['Data3'].transform('sum') 0 55 1 108 2 66 3 121 4 55 5 108 6 66 7 121 Name: Data3, dtype: int64
Es ist ein bisschen schneller,
df2 = pd.concat([df] * 12345) %timeit df2['Data3'].groupby(df['Date']).transform('sum') %timeit df2.groupby('Date')['Data3'].transform('sum') 10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Unkonventionell, aber eine Überlegung wert:
GroupBy.sum()
+Series.map()
Ich bin auf eine interessante Eigenart in der API gestoßen. Nach allem, was ich erzähle, können Sie dies auf jeder Hauptversion über 0,20 reproduzieren (ich habe dies auf 0,23 und 0,24 getestet). Es scheint, als könnten Sie konsequent einige Millisekunden der Zeit sparen, die Sie benötigen,
transform
wenn Sie stattdessen eine direkte Funktion von verwendenGroupBy
und diese senden mitmap
:df.Date.map(df.groupby('Date')['Data3'].sum()) 0 55 1 108 2 66 3 121 4 55 5 108 6 66 7 121 Name: Date, dtype: int64
Vergleichen mit
df.groupby('Date')['Data3'].transform('sum') 0 55 1 108 2 66 3 121 4 55 5 108 6 66 7 121 Name: Data3, dtype: int64
Meine Tests zeigen , dass
map
ist ein bisschen schneller , wenn Sie sich leisten können , die direkt zu verwenden ,GroupBy
Funktion (wiemean
,min
,max
,first
, etc.). Es ist mehr oder weniger schneller für die meisten allgemeinen Situationen bis zu etwa 200.000 Datensätzen. Danach hängt die Leistung wirklich von den Daten ab.(Links: v0.23, rechts: v0.24)
Schöne Alternative zu wissen, und besser, wenn Sie kleinere Frames mit einer geringeren Anzahl von Gruppen haben. . . aber ich würde empfehlen
transform
als erste Wahl . Ich dachte, das wäre es trotzdem wert, geteilt zu werden.Benchmarking-Code als Referenz:
import perfplot perfplot.show( setup=lambda n: pd.DataFrame({'A': np.random.choice(n//10, n), 'B': np.ones(n)}), kernels=[ lambda df: df.groupby('A')['B'].transform('sum'), lambda df: df.A.map(df.groupby('A')['B'].sum()), ], labels=['GroupBy.transform', 'GroupBy.sum + map'], n_range=[2**k for k in range(5, 20)], xlabel='N', logy=True, logx=True )
quelle