使用dplyr / tidyverse进行成对组合的多重测试

时间:2019-05-29 13:25:09

标签: r dplyr

我的问题与this one有关,但是是一个更复杂的示例,在该示例中,我想统计比较所有组合中的多个列,并且每个列都有不同数量的样本。

考虑原始数据:

# A tibble: 51 x 3
   trial person score
   <chr> <chr>  <dbl>
 1 foo   a      0.266
 2 bar   b      0.372
 3 foo   c      0.573
 4 bar   a      0.908
 5 foo   b      0.202
 6 bar   c      0.898
 7 foo   a      0.945
 8 bar   b      0.661
 9 foo   c      0.629
10 foo   b      0.206

对于每种试验类型,我都希望进行统计测试,以比较每个人的得分。因此,我需要以下测试结果:

  • 进行foo试验,比较A–B,B–C,C–A人的所有score个样本
  • 进行bar试验,比较A–B,B–C,C–A人的所有score个样本

当然,有两个以上的审判,三个以上的人。

因此,在另一个问题中使用group_split的解决方案不起作用,因为这意味着总是再次测试第一人称(对于我而言),而不是所有成对组合。

因此,在以下代码中,我陷入了两点:

library(tidyverse)
#> Registered S3 methods overwritten by 'ggplot2':
#>   method         from 
#>   [.quosures     rlang
#>   c.quosures     rlang
#>   print.quosures rlang
library(broom)

set.seed(1)

df = tibble::tibble(
    trial = rep(c("foo", "bar"), 30),
    person = rep(c("a", "b", "c"), 20),
    score = runif(60)
  ) %>% 
  filter(score > 0.2)

df %>% 
  group_by(person, trial) %>% 
  summarize(scores = list(score)) %>% 
  spread(person, scores) %>%
  group_split(trial) %>% 
  map_df(function(data) {
    data %>% 
      summarize_at(vars(b:c), function(x) {
        wilcox.test(.$a, x, paired = FALSE) %>% broom::tidy
      })
  })
#> Error in wilcox.test.default(.$a, x, paired = FALSE): 'x' must be numeric

reprex package(v0.3.0)于2019-05-29创建

x的值显然不仅是分数的实际列表,而且是单个试验的分数列向量。但是我不知道该如何处理每个人的样本数量不同的事实。

此外,我仍然必须手动指定列名,如果有四个以上的人员,这将是一个组合梦night。

我可以通过某种方式获得组合:

df %>% 
  group_split(trial) %>% 
  map_df(function(data) {
    combinations = expand(tibble(x = unique(data$person), y = unique(data$person)), x, y) %>% filter(x != y)
  })

…,但这实际上对创建比较列没有帮助。

我该怎么做才能使这项工作成功?

1 个答案:

答案 0 :(得分:1)

这将允许您以编程方式指定组合,并解决在wilcox.test()中遇到的错误。

combos <- unique(df$person) %>%
  combn(2, simplify = F) %>%
  set_names(map_chr(., ~ paste(., collapse = "_")))

df %>% 
  group_split(trial) %>%
  set_names(map_chr(., ~ unique(.$trial))) %>% 
  map_df(function(x) {
    map_df(combos, function(y) {
      filter(x, person %in% y) %>% 
        wilcox.test(score ~ person, data = .) %>% 
        broom::tidy()
    }, .id = "contrast")
  }, .id = "trial")

# A tibble: 6 x 6
  trial contrast statistic p.value method                 alternative
  <chr> <chr>        <dbl>   <dbl> <chr>                  <chr>      
1 bar   a_b             34   0.878 Wilcoxon rank sum test two.sided  
2 bar   a_c             32   1     Wilcoxon rank sum test two.sided  
3 bar   b_c             31   0.959 Wilcoxon rank sum test two.sided  
4 foo   a_b             41   1     Wilcoxon rank sum test two.sided  
5 foo   a_c             41   1     Wilcoxon rank sum test two.sided  
6 foo   b_c             43   0.863 Wilcoxon rank sum test two.sided  

由于此模式与您最初使用的模式有很大不同,因此我不确定它是否适用于您的实际案例,但它在这里适用,因此我想分享。