Dies sollte einfach sein, aber das Nächste, was ich gefunden habe, ist dieser Beitrag: pandas: Füllen fehlender Werte innerhalb einer Gruppe , und ich kann mein Problem immer noch nicht lösen ...
Angenommen, ich habe den folgenden Datenrahmen
df = pd.DataFrame({'value': [1, np.nan, np.nan, 2, 3, 1, 3, np.nan, 3], 'name': ['A','A', 'B','B','B','B', 'C','C','C']})
name value
0 A 1
1 A NaN
2 B NaN
3 B 2
4 B 3
5 B 1
6 C 3
7 C NaN
8 C 3
und ich möchte "NaN" mit dem Mittelwert in jeder "Namen" -Gruppe ausfüllen, d. h
name value
0 A 1
1 A 1
2 B 2
3 B 2
4 B 3
5 B 1
6 C 3
7 C 3
8 C 3
Ich bin mir nicht sicher, wohin ich gehen soll:
grouped = df.groupby('name').mean()
Vielen Dank.
python
pandas
pandas-groupby
imputation
fillna
BlueFeet
quelle
quelle
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.df["value"] = df.groupby("name")["value"].transform(lambda x: x.fillna(x.mean()))
State
undAge_Group
dann versuche ich, fehlende Werte in diesen Gruppen mit Gruppenmitteln zu füllen (aus demselben Bundesstaat innerhalb derselben Altersgruppe nehmen Mittelwerte und fehlende Werte in der Gruppe). Dankefillna
+groupby
+transform
+mean
Dies scheint intuitiv zu sein:
df['value'] = df['value'].fillna(df.groupby('name')['value'].transform('mean'))
Die
groupby
+transform
-Syntax ordnet den gruppenweisen Mittelwert dem Index des ursprünglichen Datenrahmens zu. Dies entspricht in etwa der Lösung von @ DSM , vermeidet jedoch die Notwendigkeit, eine anonymelambda
Funktion zu definieren .quelle
@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
undname
und zurechnet nur aufvalue
.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) # 0:00:00.016012 t = datetime.now() df = generate_data() df["value"] = df.groupby(['category', 'name'])\ .transform(lambda x: x.fillna(x.mean()))['value'] print(datetime.now()-t) # 0:00:00.030022
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()))
quelle
for
Schleifen dieselbe Transformation erreichen kann . Geschwindigkeit ist nicht mein Anliegen, da ich versuche, manuelle Methoden zu finden. Danke @ AndréC.AndersenIch würde es so machen
df.loc[df.value.isnull(), 'value'] = df.groupby('group').value.transform('mean')
quelle
df['value_imputed'] = np.where(df.value.isnull(), df.groupby('group').value.transform('mean'), df.value)
Die meisten der oben genannten Antworten betrafen die Verwendung von "groupby" und "transform", um die fehlenden Werte zu füllen.
Aber ich bevorzuge es, "groupby" mit "apply" zu verwenden, um die fehlenden Werte zu füllen, was für mich intuitiver ist.
>>> df['value']=df.groupby('name')['value'].apply(lambda x:x.fillna(x.mean())) >>> df.isnull().sum().sum() 0
Verknüpfung: Groupby + Apply / Lambda + Fillna + Mean
Diese Lösung funktioniert weiterhin, wenn Sie nach mehreren Spalten gruppieren möchten, um fehlende Werte zu ersetzen.
>>> df = pd.DataFrame({'value': [1, np.nan, np.nan, 2, 3, np.nan,np.nan, 4, 3], 'name': ['A','A', 'B','B','B','B', 'C','C','C'],'class':list('ppqqrrsss')}) >>> df value name class 0 1.0 A p 1 NaN A p 2 NaN B q 3 2.0 B q 4 3.0 B r 5 NaN B r 6 NaN C s 7 4.0 C s 8 3.0 C s >>> df['value']=df.groupby(['name','class'])['value'].apply(lambda x:x.fillna(x.mean())) >>> df value name class 0 1.0 A p 1 1.0 A p 2 2.0 B q 3 2.0 B q 4 3.0 B r 5 3.0 B r 6 3.5 C s 7 4.0 C s 8 3.0 C s
quelle
Die vorgestellte hochrangige Antwort funktioniert nur für einen Pandas-Datenrahmen mit nur zwei Spalten. Wenn Sie mehr Spalten haben, verwenden Sie stattdessen:
df['Crude_Birth_rate'] = df.groupby("continent").Crude_Birth_rate.transform( lambda x: x.fillna(x.mean()))
quelle
df.groupby("continent")['Crude_Birth_rate']...
Ich glaube, dies ist die vorgeschlagene Covnentiondef groupMeanValue(group): group['value'] = group['value'].fillna(group['value'].mean()) return group dft = df.groupby("name").transform(groupMeanValue)
quelle
df.fillna(df.groupby(['name'], as_index=False).mean(), inplace=True)
quelle
Sie können auch verwenden
"dataframe or table_name".apply(lambda x: x.fillna(x.mean()))
.quelle