使用t.test在dplyr中汇总多个列

21

是否有可能对多个变量针对同一分类变量进行t.test分析,而不必像下面这样重新整理数据集?

data(mtcars)
library(dplyr)
library(tidyr)
j <- mtcars %>% gather(var, val, disp:qsec)
t <- j %>% group_by(var) %>% do(te = t.test(val ~ vs, data = .))

t %>% summarise(p = te$p.value)

我尝试使用:

mtcars %>% summarise_each_(funs = (t.test(. ~ vs))$p.value, vars = disp:qsec)

但是它会报错。

额外奖励:如何使 t %>% summarise(p = te$p.value) 的结果也包括分组变量的名称?


8
您应该考虑在您的代码中添加空格。 - x4nd3r
这可能是一个由data.table提供的部分解决方案(不包括summarise部分):(步骤1)library(data.table)(步骤2)setDT(j)(步骤3)j[, te := t.test(value~vs), by=variable][] - KFB
4个回答

19

在与@aomith和@Misha的讨论之后,这里提出了一个方法。正如@aomith在他/她的评论中写道,您想要做以下操作。

mtcars %>%
    summarise_each(funs(t.test(.[vs == 0], .[vs == 1])$p.value), vars = disp:qsec)

#         vars1        vars2      vars3        vars4        vars5
#1 2.476526e-06 1.819806e-06 0.01285342 0.0007281397 3.522404e-06

vs是0或1(组)。如果您想在一个变量(例如dips)中运行两个组之间的t检验,似乎需要按照@aosmith建议的方式对数据进行子集划分。我想说感谢您的贡献。

我最初提出的建议适用于另一种情况,即您只需比较两列。以下是示例数据和代码。

foo <- data.frame(country = "Iceland",
                  year = 2014,
                  id = 1:30,
                  A = sample.int(1e5, 30, replace = TRUE),
                  B = sample.int(1e5, 30, replace = TRUE),
                  C = sample.int(1e5, 30, replace = TRUE),
                  stringsAsFactors = FALSE)

如果您想对A-C和B-C组合运行t检验,以下是一种方法。
foo2 <- foo %>%
        summarise_each(funs(t.test(., C, pair = TRUE)$p.value), vars = A:B) 

names(foo2) <- colnames(foo[4:5])

#          A         B
#1 0.2937979 0.5316822

1
@aomsith - 你能否使用t.test公式使其工作?:mtcars%>% summarise_each(funs(t.test(.〜vs)$ p.value),vars = disp:qsec)- 对我来说无法工作。 - Misha
@KonradRudolph 谢谢您的评论。我一直在思考您可能运行的代码。我认为您的意思是 mtcars %>% summarise(out = t.test(disp[vs == 0], disp[vs == 1])$p.value) 可以工作,即使您只关注一个列。您仍然可以将该列分成两个部分。但是,您可能尝试了类似这样的代码 (mtcars %>% summarise(out = t.test(filter(disp, vs == 0), filter(disp, vs == 1))$p.value)) 并发现代码返回了错误。是这样吗? - jazzurro
1
@KonradRudolph 你好。我运行了你上面的代码,但是收到了一个错误信息。我又坚持使用了 subset 并写了下面的代码。这是你想要的吗?mtcars %>% group_by(am) %>% summarize(t.test(subset(mpg, vs == 0), subset(mpg, vs == 1))$ p.value) 如果你需要更多帮助,请告诉我。我很乐意帮忙并一起思考。 - jazzurro
1
@KonradRudolph 是的,我理解你的观点。不确定为什么 filter 不起作用。filter(mtcars, vs == 0)[1] 可以工作。所以,最好的猜测是编写 mtcars %>% group_by(am) %>% summarize(out = t.test(filter(vs == 0)[1], filter(vs == 1)[1])$p.value) 或者 mtcars %>% group_by(am) %>% summarize(out = t.test(filter(.,vs == 0)[1], filter(.,vs == 1)[1])$p.value)。前者返回 Error: no applicable method for 'filter_' applied to an object of class "logical",后者返回 Error: incorrect length (19), expecting: 13 - jazzurro
1
@KonradRudolph,还有一件事情需要告诉您。如果没有使用 group_by,下面的代码可以正常工作:mtcars %>% summarize(out = t.test(filter(mtcars,vs == 0)[1], filter(mtcars,vs == 1)[1])$p.value) - jazzurro
显示剩余15条评论

14

我喜欢使用强大的 "broom" 包来解决问题:

library("dplyr")
library("broom")

your_db %>%
  group_by(grouping_variable1, grouping_variable2 ...) %>%
  do(tidy(t.test(variable_u_want_2_test ~ dicothomous_grouping_var, data = .)))

以下是一个在tidyverse中的工作示例:https://stats.stackexchange.com/questions/168378/applying-two-sample-t-test-comparing-multiple-groups-in-two-categories - Irakli

6

意译:

尽管这个问题比较老,但是为了后代的参考,我还是提供了另一个答案。

与被接受的答案相比,我的回答更为通用,因为它允许使用动态生成的变量名,而不是硬编码。

vars_to_test <- c("disp","hp","drat","wt","qsec")
iv <- "vs"

mtcars %>%
  summarise_each_(
    funs_( 
      sprintf("stats::t.test(.[%s == 0], .[%s == 1])$p.value",iv,iv)
    ), 
    vars = vars_to_test)

这将产生以下结果:

          disp           hp       drat           wt         qsec
1 2.476526e-06 1.819806e-06 0.01285342 0.0007281397 3.522404e-06

这个解决方案的想法是使用dplyr函数的SE版本( summarise_each_ 和 funs_ ),而不是NSE版本( summarise_each 和 funs ). 有关标准评估(SE)和非标准评估(NSE)的更多信息,请查看vignette("nse")。

谢谢你的解决方案!它对我有用。但是,我有两个警告信息:1:`summarise_each()已弃用,请改用summarise_if()、summarise_at()或summarise_all():
  • 要在所有变量上映射"funs",请使用summarise_all()
  • 要在一组变量上映射"funs",请使用summarise_at()和2:funs_()已弃用,请改用list()`。这段代码有更新版本吗?第二个问题,有没有办法将第二行的“1”(即此情况下的“vs”)更改为组的名称?感谢您的帮助!
- B_slash_
dplyr 更改了所有的东西,现在所有的代码都无法运行。 - Tiago Bruno

2
所以我最终编写了一个新函数: df表示数据框,by_var表示公式右侧,...所有在dplyr/tidyr中选择器左侧的变量。
例如:mult_t.test(mtcars,vs,disp:qsec)
mult_t.test<-function(df,by_var,...){
  require(dplyr)
  require(tidyr)
  by_var<-deparse(substitute(by_var))
  j<-df%>%gather(var,val,...)
  t<-j%>%group_by(var)%>%do(v=tes(.,by_var))
  k<-data.frame(levels(t$var),matrix(unlist(t$v),ncol=3,byrow = T))
  names(k)<-c("var",names(t$v[[1]]))
  k
}


tes<-function(df,vart){
  x<-t.test(df$val~df[[vart]])
  p<-x$estimate
  p<-c(p,p.val=x$p.value)
  p
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接