我正在尝试使用pandas.DataFrame.groupby['x']
来对df
分组的x
进行计算。
当'x'
重复多于一次时出现问题。 apply函数将执行'x'
重复的次数,尽管我只需要'aggregated'值(它实际上不是 aggregation ,但更像是- processing )。
这是一个玩具示例:
def simulate_complicated_func(df):
# This function simulates complicate calculations
returned_col_names = ['calc1', 'calc2', 'calc3']
df['calc1'] = ''.join(df['var1'])
df['calc2'] = df['var2'].mean()
df['calc3'] = ''.join(df['var1']) + str(df['var2'].max())
return df[['id'] + returned_col_names]
df = pd.DataFrame({'id':['id1', 'id1', 'id2', 'id3', 'id3', 'id3'],
'var1':['abc', 'cba', 'abc', 'cba', 'abc', 'cba'],
'var2':[9, 4, 7, 4, 1, 3]})
print(df)
id var1 var2
0 id1 abc 9
1 id1 cba 4
2 id2 abc 7
3 id3 cba 4
4 id3 abc 1
5 id3 cba 3
res_df = df.groupby(['id']).apply(simulate_complicated_func).drop_duplicates()
print(res_df)
id calc1 calc2 calc3
0 id1 abccba 6.500000 abccba9
2 id2 abc 7.000000 abc7
3 id3 cbaabccba 2.666667 cbaabccba4
输出正是我想要的,但是效率不高。有没有更好的方法可以使用熊猫呢?
如果我们要向print
添加simulate_complicated_func()
语句
def simulate_complicated_func(df):
# This function simulates complicate calculations
print("function called")
# ...
我们可以看到该代码将打印6次:
function called
function called
function called
function called
function called
function called
实际上,我们只需访问3次(groupby创建的组数)。
答案 0 :(得分:2)
一个想法是从自定义函数返回Series
,因此drop_duplicates
不必要:
def simulate_complicated_func(df):
# This function simulates complicate calculations
returned_col_names = ['calc1', 'calc2', 'calc3']
a = ''.join(df['var1'])
b = df['var2'].mean()
c = ''.join(df['var1']) + str(df['var2'].max())
return pd.Series([a,b,c], index=returned_col_names)
res_df = df.groupby(['id']).apply(simulate_complicated_func).reset_index()
print(res_df)
id calc1 calc2 calc3
0 id1 abccba 6.500000 abccba9
1 id2 abc 7.000000 abc7
2 id3 cbaabccba 2.666667 cbaabccba4
另一个想法是使用DataFrameGroupBy.agg
,但是它只能用于处理所有带有聚合函数(例如join
和mean
)的列。函数agg
分别与每一列一起使用,因此cal3
不可能简单/有效地计数-自定义函数和最后将输出结合在一起也是必要的:
def simulate_complicated_func(df):
# This function simulates complicate calculations
returned_col_names = ['calc3']
c = ''.join(df['var1']) + str(df['var2'].max())
return pd.Series([c], index=returned_col_names)
d = {'var1': ''.join, 'var2':'mean'}
cols = {'var1':'calc1','var2':'calc2'}
g = df.groupby(['id'])
df1 = g.agg(d).rename(columns=cols)
print (df1)
calc1 calc2
id
id1 abccba 6.500000
id2 abc 7.000000
id3 cbaabccba 2.666667
df2 = df.groupby(['id']).apply(simulate_complicated_func)
print(df2)
calc3
id
id1 abccba9
id2 abc7
id3 cbaabccba4
df = pd.concat([df1, df2], axis=1).reset_index()
print (df)
id calc1 calc2 calc3
0 id1 abccba 6.500000 abccba9
1 id2 abc 7.000000 abc7
2 id3 cbaabccba 2.666667 cbaabccba4