比较跨组样本对(来自未配对数据)的所有迭代

Compare all iterations of samples pairs (from unpaired data) across groups

我想通过平均比较两个不同的组之间所有可能的数据对来比较它们。

可重现的例子

play <- data.frame(id = c(1:7), class=rep.int(100,7),group=c(rep.int(1,3),rep.int(2,4)), value=c(2,3,2,8,7,6,7))

  id class group value
  1   100     1     2
  2   100     1     3
  3   100     1     2
  4   100     2     8
  5   100     2     7
  6   100     2     6
  7   100     2     7

所以我有 7 个样本,全部来自同一个 class,来自两个不同的组。我想要的是通过将第 2 组和第 1 组样本中的每个可能的值组合单独配对,然后对它们进行平均来计算第 2 组/第 1 组值的总体比率。

所以最后的输出值是8/2,7/2,6/2,7/2,8/3,7/3,6/3,7/3,8/2, 7/2, 6/2, 7/2 = 3.111

在我的完整数据集中,我还有更多 class,我只想在每个 class 中进行比较。每个 class/group 中的样本数量会略有不同。

我正在为如何解决这个问题而苦苦挣扎,担心我最终会陷入循环的海洋。

您可以 split 将列 value 分成两个向量,然后调用 expand.grid 以获取向量之间的所有元素对,然后对每个元素调用 /那些 Reduce 对,然后取 mean.

library(data.table)
library(magrittr)
setDT(play2)

play2[, value %>% 
          split(-group) %>% 
          do.call(what = expand.grid) %>% 
          Reduce(f = `/`) %>% 
          mean
      , by = class]

#    class       V1
# 1:   100 3.111111
# 2:   200 3.444444

使用的数据(从 AntoniosK 答案中窃取)

# example dataset
play2 <- data.frame(id = c(1:14), 
                    class=c(rep.int(100,7), rep.int(200,7)),
                    group=c(rep.int(1,3),rep.int(2,4)), 
                    value=c(2,3,2,8,7,6,7,2,3,2,8,7,6,10))

这是一个 tidyverse 解决方案。

请注意,我使用的数据集与您发布的数据集相似,但有 2 个 类,以便更接近您的真实数据集。

# example dataset
play2 <- data.frame(id = c(1:14), 
                    class=c(rep.int(100,7), rep.int(200,7)),
                    group=c(rep.int(1,3),rep.int(2,4)), 
                    value=c(2,3,2,8,7,6,7,2,3,2,8,7,6,10))

library(tidyverse)

# create a function to calculate average of ratios
GetAvgRatios = function(d) {

  expand.grid(d$value[d$group == 2],
              d$value[d$group == 1]) %>%
    mutate(v = Var1/Var2) %>%
    pull(v) %>%
    mean() }

# aplly function to the sub-dataset based on each class
play2 %>%
  nest(-class) %>%
  mutate(v = map(data, GetAvgRatios)) %>%
  select(class, v)

#   class        v
# 1   100 3.111111
# 2   200 3.444444