@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)
t = datetime.now()
df = generate_data()
df["value"] = df.groupby(['category', 'name'])\
.transform(lambda x: x.fillna(x.mean()))['value']
print(datetime.now()-t)
最后要指出的是,如果您要推算多个而不是全部的列,则可以进一步推广:
df[['value', 'other_value']] = df.groupby(['category', 'name'])['value', 'other_value']\
.transform(lambda x: x.fillna(x.mean()))
groupby
节介绍了这一点。有太多的事情要记住,但是您会选择诸如“转换是针对每个组操作的规则,这些操作要像原始帧一样被索引”之类的规则。