一种执行多个成对测试(例如 t 测试)的紧凑方法,其中单个变量以长格式拆分为多个类别

A compact way to perform multiple pairwise tests (e.g. t-test) with a single variable split in multiple categories in long-format

我有兴趣对单个变量执行多个测试,该变量具有将值分成多个组的关联因子。它与 有关,实际上,我想得到那种解决方案,但它并不完全相同。

在我的例子中,我有一个变量和多个组(最终有很多)。扩展

library(reshape)

# Create a dataset
mu=34
stdv=5
Location=rep(c("Area_A","Area_B","Area_C"),5) 
distro=rnorm(length(Location),mu,stdv) 
id=seq(1:length(Location))
sample_long=data.frame(id,Location,distro)
sample_long
   id Location   distro
1   1   Area_A 34.95737
2   2   Area_B 31.30298
3   3   Area_C 35.86569
4   4   Area_A 40.45378
5   5   Area_B 36.12060
6   6   Area_C 28.29649
7   7   Area_A 30.64495
8   8   Area_B 29.70668
9   9   Area_C 33.22874
10 10   Area_A 25.29148
11 11   Area_B 32.35511
12 12   Area_C 34.69159
13 13   Area_A 26.89791
14 14   Area_B 35.30717
15 15   Area_C 40.64628

我想在区域之间进行全对抗测试,即测试(Area_A,Area_B),测试(Area_A,Area_C)和test(Area_B,Area_C)(在更一般的情况下,所有 i<j 可能的测试)。

一种简单的方法是将数据转换为宽格式:

# Reshape to wide format
sample_wide=reshape(sample_long,direction="wide",idvar="id",timevar="Location")
sample_wide
   id distro.Area_A distro.Area_B distro.Area_C
1   1      34.95737            NA            NA
2   2            NA      31.30298            NA
3   3            NA            NA      35.86569
4   4      40.45378            NA            NA
5   5            NA      36.12060            NA
6   6            NA            NA      28.29649
7   7      30.64495            NA            NA
8   8            NA      29.70668            NA
9   9            NA            NA      33.22874
10 10      25.29148            NA            NA
11 11            NA      32.35511            NA
12 12            NA            NA      34.69159
13 13      26.89791            NA            NA
14 14            NA      35.30717            NA
15 15            NA            NA      40.64628

然后遍历所有列,我已经看到几个 approximations 比我使用 for 循环的下面一个更像 R:

# Now compute the test
test.out=list()
k=0
for(i in 2:(dim(sample_wide)[2]-1)){ # All against  all var groups
  for(j in (i+1):dim(sample_wide)[2]){
    k=k+1
    test.out[[k]]=t.test(sample_wide[,i], 
                    sample_wide[,j]) # store results in a list
  }
}

但我的问题是不是考虑到宽格式哪个是最佳解决方案,但是否有可能找到解决问题的解决方案原始的长格式,与我在上面提供的使用dplyrbroom等链接找到的解决方案一致

这比我希望的要复杂一些,也不那么简单。您可以先找出位置的组合,然后将其保存在查找 table 中以使其更简单一些。我把它变成了一个长形,每对都有一个 ID,我将把它用作数据的分组变量。

library(dplyr)
library(tidyr)
library(purrr)

set.seed(111)
# same data creation code

grps <- as.data.frame(t(combn(levels(sample_long$Location), 2))) %>%
  mutate(pair = row_number()) %>%
  gather(key, value = loc, -pair) %>%
  select(-key)

grps
#>   pair    loc
#> 1    1 Area_A
#> 2    2 Area_A
#> 3    3 Area_B
#> 4    1 Area_B
#> 5    2 Area_C
#> 6    3 Area_C

将查找加入到数据框会使行数加倍——这将根据您合并的级别数而有所不同。另请注意,我删除了您的 ID 列,因为现在似乎没有必要。嵌套,做t检验,整理结果。

sample_long %>%
  select(-id) %>%
  inner_join(grps, by = c("Location" = "loc")) %>%
  group_by(pair) %>%
  nest() %>%
  mutate(t_test = map(data, ~t.test(distro ~ Location, data = .)),
         tidied = map(t_test, broom::tidy)) %>%
  unnest(tidied)
#> # A tibble: 3 x 13
#>    pair data  t_test estimate estimate1 estimate2 statistic p.value
#>   <int> <lis> <list>    <dbl>     <dbl>     <dbl>     <dbl>   <dbl>
#> 1     1 <tib… <htes…   -0.921      31.8      32.7    -0.245   0.816
#> 2     2 <tib… <htes…   -1.48       31.8      33.3    -0.383   0.716
#> 3     3 <tib… <htes…   -0.563      32.7      33.3    -0.305   0.769
#> # … with 5 more variables: parameter <dbl>, conf.low <dbl>,
#> #   conf.high <dbl>, method <chr>, alternative <chr>

如果需要,您可以做一些事情来显示每对中的位置 - 加入查找 table 是一种方法。

我也意识到你提到过想在之后使用 broom 函数,但没有指定你 需要 一个 broom::tidy 调用。在那种情况下,只需删除最后两行。

一点基础 R 就可以解决问题:

combn(x=unique(sample_long$Location), m=2, simplify=FALSE,
      FUN=function(l) { 
        t.test(distro ~ Location, data=subset(sample_long, Location %in% l))
      })

combn 将一次生成 x 元素的所有组合 m (原文如此)。结合 subset,您会将测试应用于 data.frame.

的子集