使用 R 进行 t 检验

R
统计检验
rstatix
Author

Rui

Published

September 19, 2022

t 检验

假设数据服从正态分布(大样本情况下可以放松为对称分布),那么平均值能够很好地反映数据的总体水平。那么两份符合上述假定的数据放在一起,可以使用两样本均值的 t 检验来分析两者水平的差异。根据两样本之间是否具有相关性,又可以将 t 检验分为独立样本 t 检验和配对样本 t 检验。

独立样本 t 检验

核心函数 t.test

t.test(
  y ~ x, data, 
  alternative, mu = 0, 
  paired = FALSE,
  var.equal = FALSE,
  conf.level = 0.95,
  ...
)
t.test(
  x, y = NULL,
  alternative,
  mu = 0, 
  paired = FALSE, 
  var.equal = FALSE,
  conf.level = 0.95, 
  ...
)
  • 其中 y ~ x 在 R 中称为 formula,你可以理解为:把 x 作为自变量、y 作为因变量,将两个变量联系起来。在这里,x 为一个二分变量,y 为一个数值变量。也可以不使用这种 formula,直接指定 x 和 y

  • data 是指使用的数据,也是 x 和 y 的来源

  • alternative 可选备择假设的类型,包括 “two.sided”、“less”或”greater”。其中第一种对应双侧检验 \(H_0:\mu_1=\mu_2\),后面两种分别对应不同方向的单侧检验 \(H_0:\mu_1<\mu_2\)\(H_0:\mu_1>\mu_2\)。默认值是 “two.sided”

  • mu 默认值为 0。以双侧检验为例,通常我们想比较两样本均值的差异 \(H_0:\mu_1=\mu_2\)\(H_0:\mu_1-\mu_2=0\),但有时我们也想比较两样本均值的差值是否与我们给定的 mu 有显著差异,即 \(H_0:\mu_1-\mu_2=\mu\)

  • paired 接受一个逻辑值,默认为 FALSE,即认为两样本独立并使用独立样本 t 检验。若为 TRUE 则使用两样本配对 t 检验

  • var.equal 若为 TRUE 则假定两样本方差相等,并使用合并方差估计。与一般统计软件不同的是:R 中默认两样本方差不等(FALSE),并且使用 Welch 的修正自由度

  • conf.level confidence level(置信水平的简写),默认值为 0.95

例子:

在美国南部犯罪与在非南部犯罪被判监禁的可能性一样吗?很显然,这是一个双侧检验,并假设方差不等。使用的数据来自 MASS 包中的 UScrime

Code
library(MASS)
library(tidyverse)

UScrime %>% head(10) %>% knitr::kable()
M So Ed Po1 Po2 LF M.F Pop NW U1 U2 GDP Ineq Prob Time y
151 1 91 58 56 510 950 33 301 108 41 394 261 0.084602 26.2011 791
143 0 113 103 95 583 1012 13 102 96 36 557 194 0.029599 25.2999 1635
142 1 89 45 44 533 969 18 219 94 33 318 250 0.083401 24.3006 578
136 0 121 149 141 577 994 157 80 102 39 673 167 0.015801 29.9012 1969
141 0 121 109 101 591 985 18 30 91 20 578 174 0.041399 21.2998 1234
121 0 110 118 115 547 964 25 44 84 29 689 126 0.034201 20.9995 682
127 1 111 82 79 519 982 4 139 97 38 620 168 0.042100 20.6993 963
131 1 109 115 109 542 969 50 179 79 35 472 206 0.040099 24.5988 1555
157 1 90 65 62 553 955 39 286 81 28 421 239 0.071697 29.4001 856
140 0 118 71 68 632 1029 7 15 100 24 526 174 0.044498 19.5994 705
Code
t.test(Prob ~ So, data = UScrime) %>% 
  broom::tidy() %>% 
  knitr::kable()
estimate estimate1 estimate2 statistic p.value parameter conf.low conf.high method alternative
-0.0252 0.0385126 0.0637127 -3.895372 0.0006506 24.92514 -0.0385257 -0.0118744 Welch Two Sample t-test two.sided
Note

由于 Prob 是一个比例值,最好的处理方法是在 t 检验之前尝试对其进行正态化变换,比如:\(y/(1-y)\) 对数变换 \(\ln(y/(1-y))\)、Box-Cox 变换等。

非独立样本 t 检验

设置 paired = TRUE 即可实现非独立样本的配对 t 检验:

t.test(x, y, UScrime, paired = TRUE)
Code
sapply(UScrime[c("U1", "U2")], function (x) {c(mean=mean(x), sd=sd(x))}) %>% 
  knitr::kable()
U1 U2
mean 95.46809 33.97872
sd 18.02878 8.44545
Code
t.test(UScrime$U1, UScrime$U2, paired = TRUE) %>% 
  broom::tidy() %>% 
  knitr::kable()
estimate statistic p.value parameter conf.low conf.high method alternative
61.48936 32.40661 0 46 57.67003 65.3087 Paired t-test two.sided

批量 t 检验

使用 iris 数据集,首先进行宽数据到长数据的转换。

宽数据:

Code
iris %>% head(10) %>% knitr::kable()
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
5.1 3.5 1.4 0.2 setosa
4.9 3.0 1.4 0.2 setosa
4.7 3.2 1.3 0.2 setosa
4.6 3.1 1.5 0.2 setosa
5.0 3.6 1.4 0.2 setosa
5.4 3.9 1.7 0.4 setosa
4.6 3.4 1.4 0.3 setosa
5.0 3.4 1.5 0.2 setosa
4.4 2.9 1.4 0.2 setosa
4.9 3.1 1.5 0.1 setosa

转换为长数据:

Code
data <- iris %>% as.tibble()
data.long <- data %>% 
  pivot_longer(cols = -Species, names_to = "Variable", values_to = "Value")

data.long %>%
  head(10) %>%
  knitr::kable()
Species Variable Value
setosa Sepal.Length 5.1
setosa Sepal.Width 3.5
setosa Petal.Length 1.4
setosa Petal.Width 0.2
setosa Sepal.Length 4.9
setosa Sepal.Width 3.0
setosa Petal.Length 1.4
setosa Petal.Width 0.2
setosa Sepal.Length 4.7
setosa Sepal.Width 3.2

批量独立样本 t 检验:

Code
library(rstatix)

stat.test <- data.long %>%
  group_by(Variable) %>%
  t_test(Value ~ Species, paired = FALSE, alternative = "two.sided") %>% # 非配对t检验、双尾检验
  adjust_pvalue(method = "BH") %>% # p值调整方法,可选FDR
  add_significance(
    "p.adj", # 根据调整后的p值换算显著性符号
    cutpoints = c(0, 0.01, 0.05, 0.1, 1), 
    symbols = c("***", "**", "*", "ns") # *的数量可以自己改
  )

stat.test %>% knitr::kable()
Variable .y. group1 group2 n1 n2 statistic df p p.adj p.adj.signif
Petal.Length Value setosa versicolor 50 50 -39.492719 62.13977 0e+00 0e+00 ***
Petal.Length Value setosa virginica 50 50 -49.986186 58.60939 0e+00 0e+00 ***
Petal.Length Value versicolor virginica 50 50 -12.603779 95.57044 0e+00 0e+00 ***
Petal.Width Value setosa versicolor 50 50 -34.080342 74.75469 0e+00 0e+00 ***
Petal.Width Value setosa virginica 50 50 -42.785798 63.12262 0e+00 0e+00 ***
Petal.Width Value versicolor virginica 50 50 -14.625367 89.04338 0e+00 0e+00 ***
Sepal.Length Value setosa versicolor 50 50 -10.520986 86.53800 0e+00 0e+00 ***
Sepal.Length Value setosa virginica 50 50 -15.386196 76.51587 0e+00 0e+00 ***
Sepal.Length Value versicolor virginica 50 50 -5.629165 94.02549 2e-07 2e-07 ***
Sepal.Width Value setosa versicolor 50 50 9.454976 94.69777 0e+00 0e+00 ***
Sepal.Width Value setosa virginica 50 50 6.450349 95.54723 0e+00 0e+00 ***
Sepal.Width Value versicolor virginica 50 50 -3.205761 97.92683 2e-03 2e-03 ***