用熊猫数据框中的多个列聚合具有多个自定义函数的多列的有效方法是什么?

时间:2018-07-16 19:51:29

标签: python pandas

我有一个分组的熊猫数据框。我想聚合多个列。对于每一列,都有多个聚合函数。这很简单。棘手的是,在每个聚合函数中,我要访问另一列中的数据。

我将如何有效地做到这一点?这是我已经拥有的代码:

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()

1 个答案:

答案 0 :(得分:1)

首先,我认为您需要applyagg更多的内容来一次访问不同的列。这是一个想法,如何稍微更改您想做的事情。让我们首先创建一个函数,将要执行的操作重新分组,然后将其作为结果列表返回:

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