【问题标题】:One-sided one sample T test by group on data frame?在数据帧上按组进行单边一个样本 T 检验?
【发布时间】:2022-02-02 01:48:26
【问题描述】:

我正在尝试对 python 中的 pandas 数据框按组执行单边、一个样本 T 检验。我觉得我是如此接近,但我无法关闭最后一点。我试图关注类似于这些问题的内容(One Sided One Sample T Test PythonT-test for groups within a Pandas dataframe for a unique id)。

比如说我有一个数据框df

df = pd.DataFrame({'ID': ['A', 'A', 'A', 'A', 'A', 
                          'B', 'B', 'B', 'B', 'B', 
                          'C', 'C', 'C', 'C', 'C'],
                   'value': [0.200, 0.201, 0.189, 0.199, 0.205, 
                             0.220, 0.225, 0.209, 0.218, 0.230, 
                             0.308, 0.291, 0.340, 0.444, 0.275]})

我想生成一个只有两列的新数据框df_pval:“ID”和来自单边样本 T 检验的 p 值。我可以在 R 中这样做:

library(dplyr)

df_pval <- df %>%
     group_by(ID) %>%
     summarise(res = list(t.test(value, mu = 0.220, alternative = 'greater')))

df_pval <- data.frame(ID = df_pval$ID,
     pval = sapply(df_pval$res, function(x) x[['p.value']]))

事实上,我现在使用os 运行外部R 脚本来执行此操作,但我知道它必须在python 中才有可能。我尝试创建一个“groupby”对象,然后运行.apply

df_groupID = df.groupby('ID').agg({'value': list})
df_groupID.apply(lambda x: stats.ttest_1samp(x['value'], 0.220))

但这不起作用。截至目前,我被困住了。对此问题的任何帮助将不胜感激。提前感谢您,如果之前已经回答过这个问题,我们深表歉意(我只是不明白解决方案)。

【问题讨论】:

  • 我不知道 R (:/),所以请您展示一个包含您预期输出的示例数据框吗?

标签: python pandas dataframe dplyr scipy


【解决方案1】:

也许可以尝试这样的事情(使用scipy-1.7.3):

import pandas as pd
from scipy import stats
df = pd.DataFrame({'ID': ['A', 'A', 'A', 'A', 'A', 
                          'B', 'B', 'B', 'B', 'B', 
                          'C', 'C', 'C', 'C', 'C'],
                   'value': [0.200, 0.201, 0.189, 0.199, 0.205, 
                             0.220, 0.225, 0.209, 0.218, 0.230, 
                             0.308, 0.291, 0.340, 0.444, 0.275]})
df_groupID = df.groupby('ID').agg({'value': list})

df_groupID['value'] = df_groupID.value.apply(lambda x : stats.ttest_1samp(x, 0.220, alternative='greater').pvalue)
df_groupID = df_groupID.rename(index=str, columns={'value':'pval'})
        pval
ID          
A   0.999335
B   0.457619
C   0.010342

相当于:

library(dplyr)

df <- data.frame(
   ID = c ('A', 'A', 'A', 'A', 'A', 
                          'B', 'B', 'B', 'B', 'B', 
                          'C', 'C', 'C', 'C', 'C'), 
   value = c(0.200, 0.201, 0.189, 0.199, 0.205, 
                             0.220, 0.225, 0.209, 0.218, 0.230, 
                             0.308, 0.291, 0.340, 0.444, 0.275)
)

df_pval <- df %>%
     group_by(ID) %>%
     summarise(res = list(t.test(value, mu = 0.220, alternative = 'greater')))
df_pval <- data.frame(ID = df_pval$ID,
     pval = sapply(df_pval$res, function(x) x[['p.value']]))
print(df_pval)
  ID       pval
1  A 0.99933491
2  B 0.45761885
3  C 0.01034185

【讨论】:

  • 对于 scipy 1.5 它给出了错误TypeError: ttest_1samp() got an unexpected keyword argument 'alternative'
  • 是的,这是一个非常旧的 scipy 版本。alternative 参数还不存在。您必须更新到较新的版本。
  • 或者手动完成。
【解决方案2】:

对于单面测试,这应该适用于任何版本的 scipy:

import pandas as pd
from scipy import stats
df = pd.DataFrame({'ID': ['A', 'A', 'A', 'A', 'A', 
                          'B', 'B', 'B', 'B', 'B', 
                          'C', 'C', 'C', 'C', 'C'],
                   'value': [0.200, 0.201, 0.189, 0.199, 0.205, 
                             0.220, 0.225, 0.209, 0.218, 0.230, 
                             0.308, 0.291, 0.340, 0.444, 0.275]})


df.groupby('ID')['value'].apply(lambda x: stats.ttest_1samp(list(x),
                                popmean=0.220).pvalue/2) # divide by 2 for one-sided (alternative='greater' or 'smaller')

给予:

ID
A    0.000665
B    0.457619
C    0.010342

【讨论】:

  • 这也有效!谢谢。
猜你喜欢
  • 2018-11-19
  • 2014-05-01
  • 2022-11-22
  • 2022-11-13
  • 2017-12-14
  • 2014-03-23
  • 2017-12-10
  • 2020-09-05
  • 2019-11-08
相关资源
最近更新 更多