我有兴趣对单个变量执行多个测试,该变量具有将值分成多个组的相关因子。它与这个问题有关,实际上,我想得到这样的解决方案,但它并不完全相同。
就我而言,我有一个变量和多个组(最终是很多组(。扩展此示例:
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(和测试(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
然后遍历全对全列,为此,我已经看到了几个比我使用的 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
}
}
但是我的问题不是关于在宽格式的情况下哪个是最佳解决方案,而是是否有可能找到解决从原始长格式工作的问题的解决方案,与我上面提供的使用dplyr
、broom
等的链接找到的解决方案一致。
这比我希望的要棘手,也没那么简单。您可以先找出位置的组合,为了简化一点,将其保存在查找表中。我将其转换为一个长形状,每对都有一个 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>
如果需要,您可以执行一些操作来显示每对中的位置 - 与查找表连接将是执行此操作的一种方法。
我还意识到您提到之后想要使用broom
函数,但没有指定您需要broom::tidy
调用。在这种情况下,只需删除最后 2 行。
一点基本的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
将一次生成m
x
元素的所有组合(原文如此(。结合subset
,您将测试应用于 data.frame 的子集。