Это должно быть просто, но самое близкое, что я нашел, это этот пост: pandas: Заполнение недостающих значений внутри группы , и я все еще не могу решить свою проблему ....
Предположим, у меня есть следующий фрейм данных
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
и я хочу заполнить "NaN" средним значением в каждой группе "name", т.е.
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
Я не уверен, куда идти после:
grouped = df.groupby('name').mean()
Огромное спасибо.
python
pandas
pandas-groupby
imputation
fillna
BlueFeet
источник
источник
groupby
разделе. Слишком много вещей, которые нужно запомнить, но вы выбираете такие правила, как «преобразование выполняется для групповых операций, которые вы хотите индексировать, как исходный фрейм» и так далее.df["value"] = df.groupby("name")["value"].transform(lambda x: x.fillna(x.mean()))
State
аAge_Group
затем я пытаюсь заполнить недостающие значения в этих группах с помощью групповых средних (из того же штата в той же возрастной группе взять среднее и заполнить пропущенные значения в группе) .. Спасибоfillna
+groupby
+transform
+mean
Это кажется интуитивно понятным:
df['value'] = df['value'].fillna(df.groupby('name')['value'].transform('mean'))
groupby
+transform
Синтаксис отображает GROUPWISE среднее значение для индекса исходного dataframe. Это примерно эквивалентно решению @ DSM , но позволяет избежать необходимости определять анонимнуюlambda
функцию.источник
@DSM имеет правильный ответ IMO, но я хотел бы поделиться своим обобщением и оптимизацией вопроса: несколько столбцов для группировки и столбцы с несколькими значениями:
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], } )
... дает ...
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
В этом обобщенном случае мы хотели бы сгруппировать по
category
иname
, а вменять только поvalue
.Это можно решить следующим образом:
df['value'] = df.groupby(['category', 'name'])['value']\ .transform(lambda x: x.fillna(x.mean()))
Обратите внимание на список столбцов в предложении group-by, и что мы выбираем
value
столбец сразу после group-by. Это заставляет преобразование запускаться только в этом конкретном столбце. Вы можете добавить его в конец, но затем вы запустите его для всех столбцов, чтобы выбросить все столбцы, кроме одного, в конце. Стандартный планировщик запросов SQL мог бы оптимизировать это, но pandas (0.19.2), похоже, этого не делает.Тест производительности путем увеличения набора данных, выполнив ...
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
... подтверждает, что это увеличивает скорость пропорционально тому, сколько столбцов вам не нужно вменять:
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
В заключение вы можете обобщить еще больше, если хотите вменять более одного столбца, но не все:
df[['value', 'other_value']] = df.groupby(['category', 'name'])['value', 'other_value']\ .transform(lambda x: x.fillna(x.mean()))
источник
for
циклов. Скорость меня не волнует, так как я пытаюсь найти ручные методы. Спасибо @ AndréC.AndersenЯ бы сделал это так
df.loc[df.value.isnull(), 'value'] = df.groupby('group').value.transform('mean')
источник
df['value_imputed'] = np.where(df.value.isnull(), df.groupby('group').value.transform('mean'), df.value)
В большинстве приведенных выше ответов использовались «groupby» и «transform» для заполнения отсутствующих значений.
Но я предпочитаю использовать "groupby" с "apply" для заполнения отсутствующих значений, что для меня более интуитивно понятно.
>>> df['value']=df.groupby('name')['value'].apply(lambda x:x.fillna(x.mean())) >>> df.isnull().sum().sum() 0
Ярлык: Groupby + Apply / Lambda + Fillna + Mean
Это решение по-прежнему работает, если вы хотите сгруппировать по нескольким столбцам для замены отсутствующих значений.
>>> 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
источник
Представленный ответ с высоким рейтингом работает только для фрейма данных pandas только с двумя столбцами. Если у вас есть больше столбцов, используйте вместо этого:
df['Crude_Birth_rate'] = df.groupby("continent").Crude_Birth_rate.transform( lambda x: x.fillna(x.mean()))
источник
df.groupby("continent")['Crude_Birth_rate']...
я считаю, что это предлагаемое соглашениеdef groupMeanValue(group): group['value'] = group['value'].fillna(group['value'].mean()) return group dft = df.groupby("name").transform(groupMeanValue)
источник
df.fillna(df.groupby(['name'], as_index=False).mean(), inplace=True)
источник
Вы также можете использовать
"dataframe or table_name".apply(lambda x: x.fillna(x.mean()))
.источник