如何在r立即进行T-Test或Anova多个变量

Antoine Soetewey 2020-03-19 19 minute read

介绍

作为我在比利时大学的教学助理职位的一部分,学生们经常向我询问他们的统计学分析的帮助。

经常问题是如何在几个方面比较患者群体 定量连续 变量。我们大多数人都知道:

这两个齐鲁风采群英会是非常基本的,并且已在线和统计教科书进行广泛记录,因此难度不在如何执行这些齐鲁风采群英会中。

在过去,我曾经通过以下三个步骤进行分析:

  1. Draw boxplots illustrating the distributions by group (with the boxplot() function or thanks to the {esquisse} R Studio addin 如果我想使用 {ggplot2} package)
  2. Perform a t-test or an ANOVA depending on the number of groups to compare (with the t.test() and oneway.test() functions for t-test and ANOVA, respectively)
  3. 对每个变量重复步骤1和2

只要只有几个变量来齐鲁风采群英会,这是可行的。尽管如此,大多数学生都来找我,要求在一个或两个变量上执行这些齐鲁风采群英会,但是 倍数 变量。因此,当有一个以上的变量来齐鲁风采群英会时,我很快意识到我正在浪费我的时间,并且必须有更有效的方式来完成这项工作。

笔记:您必须非常小心,通过多次齐鲁风采群英会(也称为多重性),可以在执行多个T检验时出现。简而言之,当执行大量统计齐鲁风采群英会时,即使所有NULL假设实际上真的,某些纯粹偶然均偶然将具有小于0.05的p值。这称为多重或多次齐鲁风采群英会。您可以通过使用Bonferroni校正来解决这个问题。 Bonferroni校正是一种简单的方法,允许在保持整体置信水平的同时进行许多T检验。为此,而不是使用标准阈值 \(\ alpha = 5 \)%的级别,可以使用 \(\ alpha = \ frac {0.05} {m} \) 在哪里 \(m \) 是t检验的数量。例如,如果您使用所需的20个t检验 \(\ alpha = 0.05 \),Bonferroni校正意味着当p值小于时,您将拒绝每个单独齐鲁风采群英会的空假设 \(\ alpha = \ frac {0.05} {20} = 0.0025 \).

另请注意,没有普遍接受的方法来处理多重比较问题。通常,你应该选择一个 p - 对您的受众或您的学习领域熟悉的程度调整措施。 Bonferroni纠正是将此考虑到最常见的方法,易于实现。然而,如果您有大量的齐鲁风采群英会执行(想象您想要执行10,000 T-Tests,则是不合适的 p - value必须小于 \(\ frac {0.05} {10000} = 0.000005 \) 很重要)。一种更强大的方法还可以使用本杰里尼-Hochberg程序调整假发现速率 (麦当劳 2014)。本文旨在提出一种方法,可以从技术角度下执行多个T-Tests和Anova(如何在r中实施它)。讨论使用哪种调整方法或者是否有更合适的模型以适应数据超出本文的范围(因此请务必了解使用下面的代码的含义以获得您自己的分析)。确保齐鲁风采群英会 假设 在解释结果之前的ANOVA。

一次执行多个齐鲁风采群英会

I thus wrote a piece of code that automated the process, by drawing boxplots and performing the tests on several variables at once. Below is the code I used, illustrating the process with the iris dataset. The Species variable has 3 levels, so let’s remove one, and then draw a boxplot and apply a t-test on all 4 continuous variables at once. Note that the continuous variables that we would like to test are variables 1 to 4 in the iris dataset.

dat <- iris

# remove one level to have only two groups
dat <- subset(dat, Species != "setosa")
dat$Species <- factor(dat$Species)

# boxplots and t-tests for the 4 variables at once
for (i in 1:4) { # variables to compare are variables 1 to 4
  boxplot(dat[, i] ~ dat$Species, # draw boxplots by group
    ylab = names(dat[i]), # rename y-axis with variable's name
    xlab = "Species"
  )
  print(t.test(dat[, i] ~ dat$Species)) # print results of t-test
}

## 
##  Welch Two Sample t-test
## 
## data:  dat[, i] by dat$Species
## t = -5.6292, df = 94.025, p-value = 1.866e-07
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -0.8819731 -0.4220269
## sample estimates:
## mean in group versicolor  mean in group virginica 
##                    5.936                    6.588

## 
##  Welch Two Sample t-test
## 
## data:  dat[, i] by dat$Species
## t = -3.2058, df = 97.927, p-value = 0.001819
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -0.33028364 -0.07771636
## sample estimates:
## mean in group versicolor  mean in group virginica 
##                    2.770                    2.974

## 
##  Welch Two Sample t-test
## 
## data:  dat[, i] by dat$Species
## t = -12.604, df = 95.57, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -1.49549 -1.08851
## sample estimates:
## mean in group versicolor  mean in group virginica 
##                    4.260                    5.552

## 
##  Welch Two Sample t-test
## 
## data:  dat[, i] by dat$Species
## t = -14.625, df = 89.043, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -0.7951002 -0.6048998
## sample estimates:
## mean in group versicolor  mean in group virginica 
##                    1.326                    2.026

正如您所看到的,上面的代码绘制一个Boxplot,然后打印每个连续变量的齐鲁风采群英会结果,一切都是一次。

在过去的某个时刻,我甚至写了代码:

  1. 画一个boxplot.
  2. 齐鲁风采群英会差异平等(归功于Levene的齐鲁风采群英会)
  3. 根据差异是否相等或不相等,应用了适当的齐鲁风采群英会:韦尔奇齐鲁风采群英会如果差异不平等,如果差异在差异等方面的学生的T-Test是有关不同版本的更多细节 两个样品的T检验)
  4. 一次将步骤1到3应用于所有连续变量

在我需要比较超过两组的情况下,我对ANOVA进行了类似的代码。

该代码正在做出比较良好的工作。实际上,由于这种代码,我能够以自动的方式齐鲁风采群英会多个变量,以至于它同时比较所有变量的组。

这 only thing I had to change from one project to another is that I needed to modify the name of the grouping variable and the numbering of the continuous variables to test (Species and 1:4 in the above code).

简洁且易于解释的结果

T-Test.

虽然它很好地工作,但适用于不同的不同项目,仍然只有轻微的变化,我仍然对另一个点仍然不满意。

熟练统计和R精通的人可以读取和解释T-Test的输出,而不会遇到任何困难。然而,正如您可能已经注意到自己的统计项目,大多数人都不知道在结果中寻找什么,并且当他们在文档中看到这么多的图形,代码,输出,结果和数值时,有时会有点混淆。通过这种大量信息,它们很容易淹没。

通过我的旧r例程,我通过自动化T-Tests和Anova的过程的时间(部分地)在我不得不向学生解释R输出时丢失(部分),以便正确地解释结果。虽然大多数情况下它只是沸腾,以指出输出中寻找什么(即, p-Values),我仍然失去了很多时间,因为在我看来,这些产出是对大多数现实生活中的描述。换句话说,太多的信息似乎对许多人令人困惑,所以我仍然不相信它是将统计结果分享对非国指的最佳方式。

当然,他们来到了我统计建议,所以他们希望拥有这些结果,我需要给他们回答他们的问题和假设。尽管如此,我想找到一种更好的方法来传达这些结果的这种类型的观众,其中最少的信息才能得出结论。不再是不少的。

经过很长一段时间的在线试图以更简洁和可读的方式弄清楚呈现出现结果的方式,我发现了 {ggpubr} package。此包允许指示使用的齐鲁风采群英会和 p - 直接在基于GGPLOT2的图表上进行齐鲁风采群英会。它还有助于为非高级统计受众创建出版物议案。

经过许多改进和初始代码的修改(可用 文章),我终于想出了一个相当稳定和强大的过程,以一次执行T-Tests和Anova多个变量,更重要的是,通过任何人(统计学家或不可易读结果,使结果简洁且容易读取)。

一个图表胜过千言万语,所以这里是比上一节的完全相同的齐鲁风采群英会,但这一次与我的新r例程:

library(ggpubr)

# Edit from here #
x <- which(names(dat) == "Species") # name of grouping variable
y <- which(names(dat) == "Sepal.Length" # names of variables to test
| names(dat) == "Sepal.Width"
| names(dat) == "Petal.Length"
| names(dat) == "Petal.Width")
method <- "t.test" # one of "wilcox.test" or "t.test"
paired <- FALSE # if paired make sure that in the dataframe you have first all individuals at T1, then all individuals again at T2
# Edit until here


# Edit at your own risk
for (i in y) {
  for (j in x) {
    ifelse(paired == TRUE,
      p <- ggpaired(dat,
        x = colnames(dat[j]), y = colnames(dat[i]),
        color = colnames(dat[j]), line.color = "gray", line.size = 0.4,
        palette = "npg",
        legend = "none",
        xlab = colnames(dat[j]),
        ylab = colnames(dat[i]),
        add = "jitter"
      ),
      p <- ggboxplot(dat,
        x = colnames(dat[j]), y = colnames(dat[i]),
        color = colnames(dat[j]),
        palette = "npg",
        legend = "none",
        add = "jitter"
      )
    )
    #  Add p-value
    print(p + stat_compare_means(aes(label = paste0(..method.., ", p-value = ", ..p.format..)),
      method = method,
      paired = paired,
      # group.by = NULL,
      ref.group = NULL
    ))
  }
}

从上面的图表中看到,仅为每个变量呈现最重要的信息:

  • 由于Boxpots,群体的视觉比较
  • 统计齐鲁风采群英会的名称
  • p - 试验的价值

当然,专家可能对更高级的结果感兴趣。但是,这个简单而且完整的图表,其中包括齐鲁风采群英会的名称和 p - value,给出所有必要的信息来回答问题:“组是不同的吗?”。

在我的经验中,我注意到学生和专业人士(特别是那些从较不太科学的背景)比上一节中介绍的结果更好地了解这些结果。

这 only lines of code that need to be modified for your own project is the name of the grouping variable (Species in the above code), the names of the variables you want to test (Sepal.Length, Sepal.Width, etc.),2 whether you want to apply a t-test (t.test) or Wilcoxon test (wilcox.test) and whether the samples are paired or not (FALSE if samples are independent, TRUE if they are paired).

Based on these graphs, it is easy, even for non-experts, to interpret the results and conclude that the versicolor and virginica species are significantly different in terms of all 4 variables (since all p - 价值 \(<\ FRAC {0.05} {4} = 0.0125 \) (提醒Bonferroni校正被应用以避免多次齐鲁风采群英会的问题,因此我们划分通常的 \(\α\) 级别4,因为有4个t-tests))。

额外的 p-Value调整方法

如果你想使用另一个 p-value adjustment method, you can use the p.adjust() function. Below are the raw p - 上面发现的值 p - 从主要调整方法中派生的值(在DataFrame中呈现):

raw_pvalue <- numeric(length = length(1:4))
for (i in (1:4)) {
  raw_pvalue[i] <- t.test(dat[, i] ~ dat$Species,
    paired = FALSE,
    alternative = "two.sided"
  )$p.value
}

df <- data.frame(
  Variable = names(dat[, 1:4]),
  raw_pvalue = round(raw_pvalue, 3)
)

df$Bonferroni <-
  p.adjust(df$raw_pvalue,
    method = "bonferroni"
  )
df$BH <-
  p.adjust(df$raw_pvalue,
    method = "BH"
  )
df$Holm <-
  p.adjust(df$raw_pvalue,
    method = "holm"
  )
df$Hochberg <-
  p.adjust(df$raw_pvalue,
    method = "hochberg"
  )
df$Hommel <-
  p.adjust(df$raw_pvalue,
    method = "hommel"
  )
df$BY <-
  round(p.adjust(df$raw_pvalue,
    method = "BY"
  ), 3)
df
##       Variable raw_pvalue Bonferroni    BH  Holm Hochberg Hommel    BY
## 1 Sepal.Length      0.000      0.000 0.000 0.000    0.000  0.000 0.000
## 2  Sepal.Width      0.002      0.008 0.002 0.002    0.002  0.002 0.004
## 3 Petal.Length      0.000      0.000 0.000 0.000    0.000  0.000 0.000
## 4  Petal.Width      0.000      0.000 0.000 0.000    0.000  0.000 0.000

不管 p-Value调整方法,所有4个变量的两个物种都不同。请注意,应在查看结果之前选择调整方法,以避免根据结果选择该方法。

在另一个函数下面允许一次执行多个学生的T-Tests或Wilcoxon齐鲁风采群英会并选择 p-Value调整方法。该功能还允许指定样本是否配对或未配对,以及是否假设差异是相等的。 (代码已从Mark White的调整 文章。)

t_table <- function(data, dvs, iv,
                    var_equal = TRUE,
                    p_adj = "none",
                    alpha = 0.05,
                    paired = FALSE,
                    wilcoxon = FALSE) {
  if (!inherits(data, "data.frame")) {
    stop("data must be a data.frame")
  }

  if (!all(c(dvs, iv) %in% names(data))) {
    stop("at least one column given in dvs and iv are not in the data")
  }

  if (!all(sapply(data[, dvs], is.numeric))) {
    stop("all dvs must be numeric")
  }

  if (length(unique(na.omit(data[[iv]]))) != 2) {
    stop("independent variable must only have two unique values")
  }

  out <- lapply(dvs, function(x) {
    if (paired == FALSE & wilcoxon == FALSE) {
      tres <- t.test(data[[x]] ~ data[[iv]], var.equal = var_equal)
    }

    else if (paired == FALSE & wilcoxon == TRUE) {
      tres <- wilcox.test(data[[x]] ~ data[[iv]])
    }

    else if (paired == TRUE & wilcoxon == FALSE) {
      tres <- t.test(data[[x]] ~ data[[iv]],
        var.equal = var_equal,
        paired = TRUE
      )
    }

    else {
      tres <- wilcox.test(data[[x]] ~ data[[iv]],
        paired = TRUE
      )
    }

    c(
      p_value = tres$p.value
    )
  })

  out <- as.data.frame(do.call(rbind, out))
  out <- cbind(variable = dvs, out)
  names(out) <- gsub("[^0-9A-Za-z_]", "", names(out))

  out$p_value <- ifelse(out$p_value < 0.001,
    "<0.001",
    round(p.adjust(out$p_value, p_adj), 3)
  )
  out$conclusion <- ifelse(out$p_value < alpha,
    paste0("Reject H0 at ", alpha * 100, "%"),
    paste0("Do not reject H0 at ", alpha * 100, "%")
  )

  return(out)
}

应用于我们的数据集,没有调整方法 p - 值:

result <- t_table(
  data = dat,
  c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
  "Species"
)

result
##       variable p_value      conclusion
## 1 Sepal.Length  <0.001 Reject H0 at 5%
## 2  Sepal.Width   0.002 Reject H0 at 5%
## 3 Petal.Length  <0.001 Reject H0 at 5%
## 4  Petal.Width  <0.001 Reject H0 at 5%

和我们在一起 HOLM(1979) adjustment method:

result <- t_table(
  data = dat,
  c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width"),
  "Species",
  p_adj = "holm"
)

result
##       variable p_value      conclusion
## 1 Sepal.Length  <0.001 Reject H0 at 5%
## 2  Sepal.Width   0.002 Reject H0 at 5%
## 3 Petal.Length  <0.001 Reject H0 at 5%
## 4  Petal.Width  <0.001 Reject H0 at 5%

同样,随着HOLM的调整方法,我们得出结论,在5%的意义水平下,两种物种在所有4个变量方面都与彼此有显着不同。

Anova.

Below the same process with an ANOVA. Note that we reload the dataset iris to include all three Species this time:

dat <- iris

# Edit from here
x <- which(names(dat) == "Species") # name of grouping variable
y <- which(names(dat) == "Sepal.Length" # names of variables to test
| names(dat) == "Sepal.Width"
| names(dat) == "Petal.Length"
| names(dat) == "Petal.Width")
method1 <- "anova" # one of "anova" or "kruskal.test"
method2 <- "t.test" # one of "wilcox.test" or "t.test"
my_comparisons <- list(c("setosa", "versicolor"), c("setosa", "virginica"), c("versicolor", "virginica")) # comparisons for post-hoc tests
# Edit until here


# Edit at your own risk
for (i in y) {
  for (j in x) {
    p <- ggboxplot(dat,
      x = colnames(dat[j]), y = colnames(dat[i]),
      color = colnames(dat[j]),
      legend = "none",
      palette = "npg",
      add = "jitter"
    )
    print(
      p + stat_compare_means(aes(label = paste0(..method.., ", p-value = ", ..p.format..)),
        method = method1, label.y = max(dat[, i], na.rm = TRUE)
      )
      + stat_compare_means(comparisons = my_comparisons, method = method2, label = "p.format") # remove if p-value of ANOVA or Kruskal-Wallis test >= alpha
    )
  }
}

与T-Test的改进例程一样,我注意到学生和非专家专业人员了解Anova结果与默认的R输出相比,这种方式更容易呈现。

对于每个变量的一个图表,很容易看出所有物种都在所有4个变量中彼此不同。

If you want to apply the same automated process to your data, you will need to modify the name of the grouping variable (Species), the names of the variables you want to test (Sepal.Length, etc.), whether you want to perform an ANOVA (anova) or Kruskal-Wallis test (kruskal.test) and finally specify the comparisons for the post-hoc tests.3

走得更远

正如我们所看到的那样,这两个改进的R例程允许:

  1. 在小型或大量变量上执行T-Tests和Anova,只有对代码的次要更改。我基本上只需要替换我想要使用的变量名称和齐鲁风采群英会的名称。几乎同时齐鲁风采群英会一个或多个变量,因此与一次齐鲁风采群英会一个变量相比,它是完全改进
  2. 以一种适当和更清洁的方式分享齐鲁风采群英会结果。这是易感到的,这是可能的,图表显示了群体的观察 p-Value在此图表中包含的适当齐鲁风采群英会。这是在向更广泛的受众或来自不同背景的人们传达的结果时尤其重要。

但是,与我的大部分例程一样,这两条代码仍然是正在进行的工作。以下是我一直在考虑的其他一些功能,可以在将来添加,以使两个或多个群体更加最佳比较的过程:

  • Add the possibility to select variables by their numbering in the dataframe. For the moment it is only possible to do it via their names. This will allow to automate the process even further because instead of typing all variable names one by one, we could simply type 4:25 (to test variables 4 to 25 for instance).
  • 添加了选择a的可能性 p-Value调整方法。目前,原始 p-Values显示在图表中,然后手动调整它们。
  • 比较两组以上的组时,只有在此时可以应用ANOVA或Kruskal-Wallis齐鲁风采群英会。重大改进是为了增加执行重复措施Anova(即,当样品依赖时的ANOVA)的可能性。目前已经有可能使用两个配对样本进行T检验,但是尚不可能与两个以上的组执行相同。
  • 比较超过2组的另一个不太重要的(仍然很好)的功能将仅在拒绝ANOVA或KRUSKAL-WALLIS齐鲁风采群英会的空假设的情况下自动应用后HOC齐鲁风采群英会(所以当至少有一个时组与其他组不同,因为如果不拒绝相等组的空假设,我们不应用HOC齐鲁风采群英会)。目前,我手动添加或删除显示的代码 p-Hoc后期齐鲁风采群英会的值,具体取决于全球性 p - ANOVA或Kruskal-Wallis齐鲁风采群英会的值。

I will try to add these features in the future, or I would be glad to help if the author of the {ggpubr} 包裹 needs help in including these features (I hope he will see this article!).

最后但并非最不重要的是,一些读者可能会感兴趣:

  • 如果您想在图表上报告统计结果,我建议您检查 {ggstatsplot} package 特别是 ggbetweenstats() 功能。此函数允许在多个组或条件上进行比较连续变量。请注意,图表上显示了许多不同的统计结果,不仅是齐鲁风采群英会的名称和 p-价值。然而,能够在图上包括齐鲁风采群英会结果仍然非常方便,以便结合可视化的优点和声音统计分析。

  • {compareGroups} package 还提供了比较群体的好方法。它配备了一个非常完整的闪亮应用程序,可供选择:

# install.packages("compareGroups")
library(compareGroups)
cGroupsWUI()

谢谢阅读。我希望这篇文章能够帮助您立即对多个变量进行T-Tests和Anova,并使结果更容易被拒绝读取和解释的术语。了解更多信息 T-Test. 比较两个样本,或者 Anova. 比较3个样本或更多。

一如既往,如果您有问题或与本文所涵盖的主题相关的建议,请将其添加为评论,以便其他读者可以从讨论中受益。

参考

Holm,王子。 1979年。“简单的依次拒绝多次齐鲁风采群英会程序。” 斯堪的纳维亚统计学报65-70。

麦当劳,jh。 2014年。“多次齐鲁风采群英会。” 生物统计手册。 3埃德·巴尔的摩,马里兰州:Sparky House Publishing,233-6。


  1. 在理论上,与学生的T检验相比,ANOVA也可以使用它来比较两组,但在实践中,我们使用学生的T检验来比较两个样本和ANOVA以比较三个样本或者更多的。↩︎

  2. Do not forget to separate the variables you want to test with |.↩︎

  3. 后HOC齐鲁风采群英会仅是用于指代特定类型的统计齐鲁风采群英会的名称。后HOC齐鲁风采群英会包括Tuke HSD齐鲁风采群英会,Bonferroni校正,Dunnett的齐鲁风采群英会。即使ANOVA或KRUSKAL-WALLIS齐鲁风采群英会可以确定是否有至少一个与其他组不同的组,它也不允许我们得出结论 哪个 彼此不同。为此目的,在调整多个比较后,有一个HOC齐鲁风采群英会,它将所有组两组进行两组以确定哪些是不同的。具体地,对每个可能的组进行后HOC齐鲁风采群英会 ANOVA或Kruskal-Wallis齐鲁风采群英会表明,至少有一个不同的组(因此,“邮寄”以这种类型的齐鲁风采群英会的名称)。 NULL和替代假设和这些齐鲁风采群英会的解释类似于学生的两个样本的T检验。↩︎



喜欢这篇文章?

获取更新 每次发布新文章。
任何垃圾邮件都没有任何垃圾邮件。
分享: