首页 > 解决方案 > Pandas 在使用不带分组依据的 agg 时指定结果列名

问题描述

我正在尝试编写一个函数来总结我的熊猫数据框。这个函数应该能够按组进行汇总,也可以不分组(取决于我是否按参数指定分组)。

为了能够执行任意聚合函数,我将字典作为参数传递给 pandas agg。字典指定应该执行哪些聚合 - 理想情况下,它将指定由于我的聚合而出现的列的名称。

不幸的是,虽然我可以在使用时轻松命名所有列,但df.groupby([[).agg({})在聚合整个数据框时我无法以相同的方式指定列名(即df.agg({})

例子

让我们有一个这样的数据框:

df = pd.DataFrame(
    {
        'my_grouping_col':['A', 'A', 'B', 'B', 'C', 'C'], 
        'my_value_col_1': [1,2,3,4,5,6],
        'my_value_col_2': [7,8,9,10,11,12]
    }
)

如果我想在使用一些自定义函数时按组聚合它,我可以这样做:

df.groupby(['my_grouping_col']).agg(
    {'my_value_col_1': ['min', 'max', ('Q1', lambda x: x.quantile(0.25))], 
     'my_value_col_2':['min', 'max', ('Q3', lambda x: x.quantile(0.75))]
    }
)

因此我可以使用一个元组来指定聚合函数以及它的结果列名。

现在我希望即使不使用 groupby 也能使用相同的语法:

df.agg(
    {'my_value_col_1': ['min', 'max', ('Q1', lambda x: x.quantile(0.25))], 
         'my_value_col_2':['min', 'max', ('Q3', lambda x: x.quantile(0.75))]
    }
)

但这给了我:AttributeError: 'Q1' is not a valid function for 'Series' object

我可以想象两种我不想使用的解决方法:

选项 1: 在所有行中添加具有相同值的列,然后按 groupby。然后使用 drop=True 重置索引以删除此列。

df['my_temporary_grouping_column'] = 1
df.groupby(['my_temporary_grouping_column']).agg(
    {'my_value_col_1': ['min', 'max', ('Q1', lambda x: x.quantile(0.25))], 
     'my_value_col_2':['min', 'max', ('Q3', lambda x: x.quantile(0.75))]
    }
).reset_index(drop = True)

这给出了预期的结果:

    my_value_col_1  my_value_col_2
    min max Q1      min max Q3
my_grouping_col                     
A   1   2   1.25    7   8   7.75
B   3   4   3.25    9   10  9.75
C   5   6   5.25    11  12  11.75

选项 2

没有 groupby 的聚合为:

df.agg(
    {'my_value_col_1': ['min', 'max', lambda x: x.quantile(0.25)], 
     'my_value_col_2':['min', 'max', lambda x: x.quantile(0.75)]
    }
)

并重命名......但我认为第二个选项真的不切实际。

我可以以某种方式更改指定聚合详细信息的字典(包括指定列名),以便它在两种情况下都有效 - 使用 groupby 和不使用 groupby?如果不是在没有 groupby 的情况下在 agg 中指定列名的好方法是什么?请注意,我不希望使用类似的东西:agg(Q3 = lambda x: x.quantile(0.75)). 我想在一个函数中使用代码,该函数将应该执行哪些聚合的详细信息作为参数,例如:

def summarise(data, columns, group_cols, functions):
    tdict = {}
    [tdict.update({i.functions}) for i in columns]
    if group_cols is not None:
        out = data.groupby(group_cols).agg(tdict)
    else:
        data['temporary_group_col'] = 1
        out = data.groupby(['temporary_group_col']).agg(tdict).reset_index(drop = True)
    return out

标签: pandasdataframegroup-byaggregate

解决方案


推荐阅读