我需要创建一个多功能函数,并将其传输到pandas
DataFrame中,以便对未指定数量的组和子组运行ANOVA。我有一些DataFrame,其中包含两个分类列(这里是cat1
和cat2
)和一些连续列(这里只有contin_1
和contin2
)。
cat1 cat2 contin_Z contin_Y ...
0 A 1 08 33
1 B 1 00 86
2 C 2 85 65
3 A 1 82 08
4 A 2 90 85
5 A 3 93 93
6 A 2 13 65
7 A 1 33 90
8 B 2 00 10
9 C 2 58 57
10 C 1 68 68
11 B 1 43 40
12 A 1 35 NaN
13 A 3 75 40
14 A 3 68 53
15 A 2 93 93
16 B 3 18 65
17 C 3 33 28
18 A 1 50 94
19 B 1 25 90
对于上面的示例数据,我希望按cat1
对它进行分组,并对每个cat1
组的所有cat2
组进行ANOVA,同时输出每个cat1
/cat2
组合的平均值。我希望能够在不考虑连续列数的情况下进行此操作--有点像pandas.DataFrame.groupby.mean
可以对任意数量的列进行操作。
输出应如下所示,具有某种形状:(这是一个示例输出,只是为了显示我正在寻找的输出的形状;平均值和p值是无意义值。
cat1 cat2 Z_mean Z_anova_pval Y_mean Y_anova_pval ...
0 A 1 54 .005 43 .076
1 A 2 73 .005 34 .076
2 A 3 34 .005 42 .076
3 B 1 76 .567 32 .002
4 B 2 98 .567 78 .002
5 B 3 73 .567 101 .002
6 C 1 84 .043 15 .041
7 C 2 23 .043 43 .041
8 C 3 82 .043 87 .041
我想这个函数应该是这样的:
data.groupby('cat1').pipe(f)
最接近我需要的函数是这行代码,它通过一个生成器表达式将所有cat2
子组传递给f_oneway
,但我不知道如何在cat1
上的groupby
中完成此操作,尤其是在获取平均值时,我想可能需要单独使用groupby.agg
来完成此操作,但我不确定如何使其可伸缩到DataFrame中的任意多个连续列。
from scipy import stats
def run_anova(data):
return stats.f_oneway(*(data[data.cat2==cat].dropna() for cat in data.cat2.unique()))
编辑:沿着这条线的东西似乎产生了一个准确的p值方面的结果。
from scipy.stats import f_oneway as anova
continuous_cols = [ ... list of all desired continuous cols ... ]
cats = data.cat1.unique()
pvals = (
data
.groupby(['cat2'])[continuous_cols]
.agg(
lambda x:
anova(*[x[data.cat1==cat].dropna() for cat in cats])[0]
)
)
> contin_Z contin_Y
> cat2
> 1 .045 .087
> 2 .654 .945
> 3 .943 .003
但是,我不知道如何将其与需要每个子组的平均值相结合(除了执行两个GroupBys,然后在重置平均值表上的一个索引级别后合并):
pvals = pvals.add_suffix('_pval')
means = data.groupby(['cat2', 'cat1'])[continuous_cols].mean()
means = means.add_suffix('_mean')
table = (
pvals
.merge(means.reset_index(level=1), left_index=True, right_index=True)
)
2条答案
按热度按时间hivapdat1#
您已经对所涉及的步骤有了很好的了解。这里的要点是,平均值和p值是在两个不同的聚总层上计算的:
(cat2, cat1)
水平计算平均值cat2
级别计算p值data.groupby(...).pipe(f)
的想法实际上并不可行,因为它将你限制在一个水平上。下面的解决方案将分别计算均值和p值,然后将它们结合在一起。它不需要你事先列出连续变量,也不需要改变代码来容纳新变量,它只关心分类变量,这些变量在你的用例中是固定的。
结果:
jdgnovmf2#
我不知道我是否理解了你的问题,但这能帮助你吗?
现在,它应该考虑到你所拥有的尽可能多的连续变量,为每个2个变量的组合创建一个p_value列。不要介意
data['cont1'].astype(float)
的事情,is只是让变量浮动。如果你的df已经包含十进制值,你就不需要它了。