Blu*_*eet 57 python pandas imputation fillna pandas-groupby
这应该是直截了当的,但我发现的最接近的是这篇文章: 熊猫:填写组内的缺失值,我仍然无法解决我的问题....
假设我有以下数据帧
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
Run Code Online (Sandbox Code Playgroud)
并且我想在每个"名称"组中填写"NaN",其中包含平均值
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
Run Code Online (Sandbox Code Playgroud)
我不确定去哪里:
grouped = df.groupby('name').mean()
Run Code Online (Sandbox Code Playgroud)
谢谢一堆.
DSM*_*DSM 74
一种方法是使用transform:
>>> df
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
>>> df["value"] = df.groupby("name").transform(lambda x: x.fillna(x.mean()))
>>> df
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
Run Code Online (Sandbox Code Playgroud)
And*_*sen 18
@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],
}
)
Run Code Online (Sandbox Code Playgroud)
......给...
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
Run Code Online (Sandbox Code Playgroud)
在这种情况下,广义我们想通过组category和name,只有在推诿value.
这可以解决如下:
df['value'] = df.groupby(['category', 'name'])['value']\
.transform(lambda x: x.fillna(x.mean()))
Run Code Online (Sandbox Code Playgroud)
注意group-by子句中的列列表,我们选择valuegroup-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
Run Code Online (Sandbox Code Playgroud)
...确认这会增加速度与您不必估算的列数成比例:
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
Run Code Online (Sandbox Code Playgroud)
最后一点,如果你想要输入多个列,而不是全部列,你可以进一步概括:
df[['value', 'other_value']] = df.groupby(['category', 'name'])['value', 'other_value']\
.transform(lambda x: x.fillna(x.mean()))
Run Code Online (Sandbox Code Playgroud)
jpp*_*jpp 14
fillna+ groupby+ transform+mean这看起来很直观:
df['value'] = df['value'].fillna(df.groupby('name')['value'].transform('mean'))
Run Code Online (Sandbox Code Playgroud)
本groupby+ transform语法的GroupWise平均映射到原始数据帧的指数。这大致相当于@DSM的解决方案,但避免了定义匿名lambda函数的需要。
Ash*_*and 13
捷径:
Groupby + Apply + Lambda + Fillna + Mean
>>> df['value1']=df.groupby('name')['value'].apply(lambda x:x.fillna(x.mean()))
>>> df.isnull().sum().sum()
0
Run Code Online (Sandbox Code Playgroud)
如果您想按多列分组以替换缺失值,此解决方案仍然有效。
>>> 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']=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
Run Code Online (Sandbox Code Playgroud)
piR*_*red 10
我这样做
df.loc[df.value.isnull(), 'value'] = df.groupby('group').value.transform('mean')
Run Code Online (Sandbox Code Playgroud)
特色高排名答案仅适用于只有两列的熊猫数据框。如果您有更多列案例,请改用:
df['Crude_Birth_rate'] = df.groupby("continent").Crude_Birth_rate.transform(
lambda x: x.fillna(x.mean()))
Run Code Online (Sandbox Code Playgroud)