Pandas:聚合多个函数并将其应用于同一列
Pandas: Aggregating and applying multiple functions to same column
我有一个 pandas 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
是我在整个过程中做任何事情的唯一专栏,我可以只做 Pandas 文档中描述的 "Applying multiple functions at once." 但是,我正在尝试两者都做多列和多个功能。当它只是 "multiple functions at once" 情况时,我可以明确命名输出列,但当涉及多个列时,我无法弄清楚如何去做。现在,当我尝试在一个 agg(...)
步骤中完成所有操作时,val_2
p 值列定义覆盖了原始均值列定义,因为它们都在同一个 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
?
(参见我的另一个密切相关的 agg
问题 。)
你可以试试这个。我正在传递 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
根据您在下方的评论,您可以"flatten"您的专栏
你可以降低一个级别
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
这可能是更好的选择。它使用列表 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
我有一个 pandas 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
是我在整个过程中做任何事情的唯一专栏,我可以只做 Pandas 文档中描述的 "Applying multiple functions at once." 但是,我正在尝试两者都做多列和多个功能。当它只是 "multiple functions at once" 情况时,我可以明确命名输出列,但当涉及多个列时,我无法弄清楚如何去做。现在,当我尝试在一个 agg(...)
步骤中完成所有操作时,val_2
p 值列定义覆盖了原始均值列定义,因为它们都在同一个 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
?
(参见我的另一个密切相关的 agg
问题
你可以试试这个。我正在传递 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
根据您在下方的评论,您可以"flatten"您的专栏
你可以降低一个级别
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
这可能是更好的选择。它使用列表 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