@DSM hat IMO die richtige Antwort, aber ich möchte meine Verallgemeinerung und Optimierung der Frage teilen: Mehrere Spalten zum Gruppieren und mit mehreren Wertespalten:
df = pd.DataFrame(
{
'category': ['X', 'X', 'X', 'X', 'X', 'X', 'Y', 'Y', 'Y'],
'name': ['A','A', 'B','B','B','B', 'C','C','C'],
'other_value': [10, np.nan, np.nan, 20, 30, 10, 30, np.nan, 30],
'value': [1, np.nan, np.nan, 2, 3, 1, 3, np.nan, 3],
}
)
... gibt ...
category name other_value value
0 X A 10.0 1.0
1 X A NaN NaN
2 X B NaN NaN
3 X B 20.0 2.0
4 X B 30.0 3.0
5 X B 10.0 1.0
6 Y C 30.0 3.0
7 Y C NaN NaN
8 Y C 30.0 3.0
In diesem verallgemeinerten Fall würden wir gerne Gruppe durch category
und name
und zurechnet nur auf value
.
Dies kann wie folgt gelöst werden:
df['value'] = df.groupby(['category', 'name'])['value']\
.transform(lambda x: x.fillna(x.mean()))
Beachten Sie die Spaltenliste in der Gruppierungsklausel und dass wir die value
Spalte direkt nach der Gruppierungsklausel auswählen . Dadurch wird die Transformation nur für diese bestimmte Spalte ausgeführt. Sie können es am Ende hinzufügen, aber dann werden Sie es für alle Spalten ausführen, um am Ende alle bis auf eine Messspalte zu löschen. Ein Standard-SQL-Abfrageplaner hätte dies möglicherweise optimieren können, aber Pandas (0.19.2) scheint dies nicht zu tun.
Leistungstest durch Erhöhen des Datensatzes durch Ausführen von ...
big_df = None
for _ in range(10000):
if big_df is None:
big_df = df.copy()
else:
big_df = pd.concat([big_df, df])
df = big_df
... bestätigt, dass dies die Geschwindigkeit proportional zu der Anzahl der Spalten erhöht, die Sie nicht unterstellen müssen:
import pandas as pd
from datetime import datetime
def generate_data():
...
t = datetime.now()
df = generate_data()
df['value'] = df.groupby(['category', 'name'])['value']\
.transform(lambda x: x.fillna(x.mean()))
print(datetime.now()-t)
t = datetime.now()
df = generate_data()
df["value"] = df.groupby(['category', 'name'])\
.transform(lambda x: x.fillna(x.mean()))['value']
print(datetime.now()-t)
Abschließend können Sie noch weiter verallgemeinern, wenn Sie mehr als eine Spalte, aber nicht alle unterstellen möchten:
df[['value', 'other_value']] = df.groupby(['category', 'name'])['value', 'other_value']\
.transform(lambda x: x.fillna(x.mean()))
groupby
Abschnitt behandelt. Es gibt zu viel zu merken, aber Sie lernen Regeln wie "Transformation ist für Operationen pro Gruppe, die wie der ursprüngliche Frame indiziert werden sollen" und so weiter.