R 从具有重复项的数据创建组,以便每个组都有一个表示一次的重复项

R 从具有重复项的数据创建组,以便每个组都有一个表示一次的重复项,r,data.table,R,Data.table,我对大约3000个样本进行了测序。样本最初被标记,并通过PCR进行重复扩增。使用的标记范围从Tag1到Tag26 第1对使用Tag1-Tag13,第2对使用Tag14-Tag26。这些标记被重新使用,以允许合并样本 合并过程将涉及将标签为1-26的样本混合到第一组中,将标签为1-26的下一个样本混合到第二组中,依此类推。值得注意的是,有时会丢失一些标签,因为相应的样本未能放大 在去实验室之前,我需要先把这些小组写在纸上 这是分组前的样本快照。(注意,Tag01至Tag05用于样本数据集中的Tag

我对大约3000个样本进行了测序。样本最初被标记,并通过PCR进行重复扩增。使用的标记范围从Tag1到Tag26

第1对使用Tag1-Tag13,第2对使用Tag14-Tag26。这些标记被重新使用,以允许合并样本

合并过程将涉及将标签为1-26的样本混合到第一组中,将标签为1-26的下一个样本混合到第二组中,依此类推。值得注意的是,有时会丢失一些标签,因为相应的样本未能放大

在去实验室之前,我需要先把这些小组写在纸上

这是分组前的样本快照。(注意,
Tag01
Tag05
用于样本数据集中的
TagA
Tag06
Tag10
用于
TagB
。)

这是分组后的相同数据

postGroup <- structure(list(SampleID = c(1L, 2L, 3L, 4L, 5L, 6L, 8L, 9L, 10L, 
11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 7L), TagA = structure(c(3L, 
4L, 5L, 3L, 4L, 5L, 2L, 3L, 1L, 2L, 3L, 1L, 3L, 4L, 1L, 2L, 3L, 
4L, 1L), .Label = c("Tag01", "Tag02", "Tag03", "Tag04", "Tag05"
), class = "factor"), TagB = structure(c(5L, 1L, 2L, 4L, 5L, 
1L, 2L, 3L, 5L, 1L, 2L, 3L, 4L, 5L, 2L, 3L, 4L, 5L, 1L), .Label = c("Tag06", 
"Tag07", "Tag08", "Tag09", "Tag10"), class = "factor"), group = structure(c(1L, 
1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 5L, 5L, 5L, 5L, 6L, 
6L, 7L), .Label = c("group1", "group2", "group3", "group4", "group5", 
"group6", "group7"), class = "factor")), class = "data.frame", row.names = c(NA, 
-19L))
我正在寻找一个R脚本,可以创建这些组,因为我们习惯于使用少于50个样本,我们将手动创建组,但是,这个任务的规模是压倒性的


最后,由于样本数在1000,因此如果代码能够尽可能地保持样本的原始顺序,即样本1更接近样本50,而不是样本500,则会更好,以便在实验室中实现简单的顺序检索过程(我希望这里有意义…)

如果我理解正确,OP希望对他的样本进行分组,以便

  • 每组包含尽可能多的样本
  • 每个组仅包含一个不同的
    TagA
    元素和一个不同的
    TagB
    元素
  • 样品尽可能按原始顺序保存
  • 下面的方法通过将所有样本放在一个组中,然后查找(从上到下)放在下一个组中的任何重复样本来迭代工作。这将继续,直到找不到具有重复项的组为止

    此处使用,因为它能够通过引用进行更新,即不复制整个对象

    library(data.table)
    grouped <- as.data.table(preGroup)[order(SampleID)][, group := 1L][]
    max_grp <- 1L
    while (any(grouped[, anyDuplicated(TagA) | anyDuplicated(TagB), by = group]$V1)) {
      max_grp <- max_grp + 1L
      dups <- duplicated(grouped, by = c("group", "TagA")) | 
        duplicated(grouped, by = c("group", "TagB"))
      grouped[dups, group := max_grp][]
      stopifnot(max_grp <= nrow(grouped)) # just to prevent infinite looping
    }
    grouped
    
    注意,这个结果比OP手工挑选的
    postGroup
    少了一组,后者包含第七组,只有一个样本

    我们可以执行一些检查来验证条件2。满足以下条件:

    grouped[, anyDuplicated(TagA), by = group]
    

    这可能不是最有效的方法和/或实施。然而,在开始考虑优化之前,我想手头上有一些能够提供预期结果的东西。

    谢谢@Uwe,太棒了!!特别是尽量保持样品的秩序。快速提问,如果用户不介意样本的顺序(这种情况是可以预见的)…你将如何实现…?如果目标是最小化总体组的数量,这可能会导致一般的优化问题(可能类似于“背包问题”)。我理解最小化总体组数量的必要性。然而,正如我在前面的评论中提到的,条件的变化导致了一个不同的问题。因此,我恭敬地建议你提出一个新问题,强调需要尽量减少群体数量。谢谢。注意,再次感谢@Uwe。。
       SampleID  TagA  TagB  group
    1         1 Tag03 Tag10 group1
    2         2 Tag04 Tag06 group1
    3         3 Tag05 Tag07 group1
    4         4 Tag03 Tag09 group2
    5         5 Tag04 Tag10 group2
    6         6 Tag05 Tag06 group2
    7         8 Tag02 Tag07 group2
    8         9 Tag03 Tag08 group3
    9        10 Tag01 Tag10 group3
    10       11 Tag02 Tag06 group3
    11       12 Tag03 Tag07 group4
    12       13 Tag01 Tag08 group4
    13       14 Tag03 Tag09 group5
    14       15 Tag04 Tag10 group5
    15       16 Tag01 Tag07 group5
    16       17 Tag02 Tag08 group5
    17       18 Tag03 Tag09 group6
    18       19 Tag04 Tag10 group6
    19        7 Tag01 Tag06 group7
    
    library(data.table)
    grouped <- as.data.table(preGroup)[order(SampleID)][, group := 1L][]
    max_grp <- 1L
    while (any(grouped[, anyDuplicated(TagA) | anyDuplicated(TagB), by = group]$V1)) {
      max_grp <- max_grp + 1L
      dups <- duplicated(grouped, by = c("group", "TagA")) | 
        duplicated(grouped, by = c("group", "TagB"))
      grouped[dups, group := max_grp][]
      stopifnot(max_grp <= nrow(grouped)) # just to prevent infinite looping
    }
    grouped
    
        SampleID  TagA  TagB group
     1:        1 Tag03 Tag10     1
     2:        2 Tag04 Tag06     1
     3:        3 Tag05 Tag07     1
     4:        4 Tag03 Tag09     2
     5:        5 Tag04 Tag10     2
     6:        6 Tag05 Tag06     2
     7:        7 Tag01 Tag06     3
     8:        8 Tag02 Tag07     2
     9:        9 Tag03 Tag08     3
    10:       10 Tag01 Tag10     4
    11:       11 Tag02 Tag06     4
    12:       12 Tag03 Tag07     4
    13:       13 Tag01 Tag08     5
    14:       14 Tag03 Tag09     5
    15:       15 Tag04 Tag10     5
    16:       16 Tag01 Tag07     6
    17:       17 Tag02 Tag08     6
    18:       18 Tag03 Tag09     6
    19:       19 Tag04 Tag10     6
    
    grouped[, anyDuplicated(TagA), by = group]
    
       group V1
    1:     1  0
    2:     2  0
    3:     3  0
    4:     4  0
    5:     5  0
    6:     6  0
    
    grouped[, anyDuplicated(TagB), by = group]
    
       group V1
    1:     1  0
    2:     2  0
    3:     3  0
    4:     4  0
    5:     5  0
    6:     6  0