我有一个分组的熊猫数据框。我想聚合多个列。对于每一列,都有多个聚合函数。这很简单。棘手的是,在每个聚合函数中,我要访问另一列中的数据。
我将如何有效地做到这一点?这是我已经拥有的代码:
import pandas
data = [
{
'id': 1,
'A': 1,
'B': 1,
'C': 1,
'D': 1,
'E': 1,
'F': 1,
},
{
'id': 1,
'A': 2,
'B': 2,
'C': 2,
'D': 2,
'E': 2,
'F': 2,
},
{
'id': 2,
'A': 3,
'B': 3,
'C': 3,
'D': 3,
'E': 3,
'F': 3,
},
{
'id': 2,
'A': 4,
'B': 4,
'C': 4,
'D': 4,
'E': 4,
'F': 4,
},
]
df = pandas.DataFrame.from_records(data)
def get_column(column, column_name):
return df.iloc[column.index][column_name]
def agg_sum_a_b(column_a):
return column_a.sum() + get_column(column_a, 'B').sum()
def agg_sum_a_b_divide_c(column_a):
return (column_a.sum() + get_column(column_a, 'B').sum()) / get_column(column_a, 'C').sum()
def agg_sum_d_divide_sum_e_f(column_d):
return column_d.sum() / (get_column(column_d, 'E').sum() + get_column(column_d, 'F').sum())
def multiply_then_sum(column_e):
return (column_e * get_column(column_e, 'F')).sum()
df_grouped = df.groupby('id')
df_agg = df_grouped.agg({
'A': [agg_sum_a_b, agg_sum_a_b_divide_c, 'sum'],
'D': [agg_sum_d_divide_sum_e_f, 'sum'],
'E': [multiply_then_sum]
})
此代码产生以下数据帧:
A D E
agg_sum_a_b agg_sum_a_b_divide_c sum agg_sum_d_divide_sum_e_f sum multiply_then_sum
id
1 6 2 3 0.5 3 5
2 14 2 7 0.5 7 25
我这样做正确吗?有更好的方法吗?我发现在聚合函数中另一列中访问数据的方式有点尴尬。
我正在使用的实际数据和代码大约有20列和大约40个聚合函数。可能还有数百个组,每个组有数百行。
当我使用实际数据和聚合函数执行此操作时,可能要花几分钟,这对于我的目的来说太慢了。有什么方法可以提高效率吗?
编辑:我正在使用Python 3.6和pandas 0.23.0 btw。谢谢!
编辑2:添加了一个示例,其中我没有在列上调用sum()
。
答案 0 :(得分:1)
首先,我认为您需要apply
比agg
更多的内容来一次访问不同的列。这是一个想法,如何稍微更改您想做的事情。让我们首先创建一个函数,将要执行的操作重新分组,然后将其作为结果列表返回:
def operations_to_perfom (df_g):
df_g_sum = df_g.sum() #can do the same with mean, min, max ...
# return all the operation you want
return [ df_g_sum['A'] + df_g_sum['B'],
(df_g_sum['A'] + df_g_sum['B'])/df_g_sum['C'],
df_g_sum['A'],
float(df_g_sum['D'])/(df_g_sum['E']+df_g_sum['F']),
(df_g['E']*df_g['F']).sum() ]
#use apply to create a serie with id as index and a list of agg
df_values = df.groupby('id').apply(operations_to_perfom)
# now create the result dataframe from df_values with tolist() and index
df_agg = pd.DataFrame( df_values.tolist(), index=df_values.index,
columns=pd.MultiIndex.from_arrays([['A']*3+['D']+['E'],
['agg_sum_a_b', 'agg_sum_a_b_div_c' ,'sum', 'agg_sum_d_div_sum_e_f', 'e_mult_f']]))
和df_agg
如下:
A D E
agg_sum_a_b agg_sum_a_b_div_c sum agg_sum_d_div_sum_e_f e_mult_f
id
1 6 2 3 0.5 5
2 14 2 7 0.5 25