Pandas:将多个函数聚合并应用于同一列

时间:2015-04-18 19:27:53

标签: python pandas scipy

我有一只像这样的大熊猫DataFrame

n = 6000
my_data = DataFrame ({
    "Category"  : np.random.choice (['cat1','cat2'], size=n) ,
    "val_1"     : np.random.randn(n) ,
    "val_2"     : [i for i in range (1,n+1)]
})

我想计算一列的计数和其他两列的平均值,按Category汇总。这在pandas文档中描述为"Applying different functions to DataFrame columns",我这样做:

counts_and_means = \
    my_data.groupby("Category").agg (
        {
            "Category"  : np.count_nonzero ,
            "val_1"     : np.mean ,
            "val_2"     : np.mean
        }
    )

我还想计算val_2的t检验p变量,检验val_2的均值为零的假设。如果val_2是我在整个过程中唯一做过的任何专栏,我可以按照"Applying multiple functions at once."的方式执行Pandas文档中描述的内容但是,我尝试同时执行多个列和多个功能。当输出列只是"多个函数时,我可以明确地命名输出列#34;但是,当涉及多个列时,我无法弄清楚如何做到这一点。现在,当我尝试在agg(...)步骤中完成所有操作时,val_2 p值列定义会覆盖原始平均列定义,因为它们都在同一个{{1}中}。所以,我最终需要创建第二个dict并加入它们:

DataFrame

我的问题:是否有一些方法可以在一个val_tests = \ my_data.groupby("Category").agg ( { "val_2" : lambda arr : sp.stats.ttest_1samp(arr, popmean=0)[1] } ) \ .rename (columns={"val_2" : "p_val_2"}) results = pd.merge(counts_and_means, val_tests, left_index=True, right_index=True) 步骤中执行此操作,而无需创建第二个结果agg(...)并执行DataFrame

(请参阅我的其他密切相关的merge问题here。)

1 个答案:

答案 0 :(得分:2)

你可以试试这个。我传递了val_2的函数列表

def ttest(arr):     
    return stats.ttest_1samp(arr, popmean=0)[1]

counts_and_means = \
    my_data.groupby("Category").agg (
        {
            "Category"  : np.count_nonzero ,
            "val_1"     : np.mean ,
            "val_2"     : [np.mean,ttest]
        }
    )

如果你喜欢稍短的版本

counts_and_means = \
    my_data.groupby("Category").agg (
        {
            "Category"  : np.count_nonzero ,
            "val_1"     : np.mean ,
            "val_2"     : [np.mean,lambda arr : stats.ttest_1samp(arr, popmean=0)[1]]
        }
    )

这会产生

     Category      val_1            val_2
         count_nonzero  mean        mean    ttest
Category                
cat1     3059           0.007861    2990.997712 0
cat2     2941          -0.007450    3010.383543 0

根据您的评论,您可以"展平"你的专栏

你可以放弃一个级别

counts_and_means.columns = counts_and_means.columns.droplevel()
counts_and_means

但是会删除顶层,留下重复的列名

           count_nonzero    mean        mean       ttest
Category                
cat1       3059             0.007861    2990.997712 0
cat2       2941            -0.007450    3010.383543 0

这可能是更好的选择。它使用list comp来连接我从here

获得的列名
counts_and_means.columns = ['%s%s' % (a, '_%s' % b if b else '') 
                           for a, b in counts_and_means.columns]
counts_and_means

            Category_count_nonzero  val_1_mean  val_2_mean   val_2_ttest
Category                
cat1        3059                    0.007861    2990.997712  0
cat2         2941                  -0.007450    3010.383543  0