combn-like 组合作为 R 中元素的任务

combn-like task for combinations as elements in R

不确定我是否选择了一个好的标题...我也不知道我是否使用了正确的术语,所以也许使用正确的搜索词我会找到解决这个问题的方法...

我有一个字符串列表,我希望从中得到所有 "exclusive" 组 3.

的组合

示例: 与以下

require(utils)
mylist<-c("strA","strB","strC","strD","strE","strF")
t(combn(mylist,3))

我得到一个 table,它列出了这 6 个字符串中 3 个的所有可能组合(因此每一行代表 3 个的一个组合):

        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strC"
   [2,] "strA" "strB" "strD"
   [3,] "strA" "strB" "strE"
   [4,] "strA" "strB" "strF"
   [5,] "strA" "strC" "strD"
   [6,] "strA" "strC" "strE"
   [7,] "strA" "strC" "strF"
   [8,] "strA" "strD" "strE"
   [9,] "strA" "strD" "strF"
  [10,] "strA" "strE" "strF"
  [11,] "strB" "strC" "strD"
  [12,] "strB" "strC" "strE"
  [13,] "strB" "strC" "strF"
  [14,] "strB" "strD" "strE"
  [15,] "strB" "strD" "strF"
  [16,] "strB" "strE" "strF"
  [17,] "strC" "strD" "strE"
  [18,] "strC" "strD" "strF"
  [19,] "strC" "strE" "strF"
  [20,] "strD" "strE" "strF"

但我想要所有 3 的组合,其中每个字符串只出现一次。所以我想要的输出看起来像这样:


        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strC"
   [2,] "strD" "srtE" "strF"

        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strD"
   [1,] "strC" "strE" "strF"

        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strE"
   [1,] "strC" "strD" "strF"
...

所以这里每个子元素(</code>、<code></code> 等)包含 3 个字符串的 2 个组合(如 2*3=6;有 6 个字符串)。在每组中,每个字符串不得出现超过一次。 </p> <p>当然,如果 <code>mylist 的长度不是 n=3 的倍数,这也是可能的,那就太好了。如果我们假设有 10 个字符串(加上 "strG"、"strH"、"strI" 和 "strJ"),我想在每个组合中省略一个字符串.所以想要的结果会像


        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strC"
   [2,] "strD" "strE" "strF"
   [3,] "strG" "strH" "strI"

        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strC"
   [2,] "strD" "strE" "strF"
   [3,] "strG" "strH" "strJ"

        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strC"
   [2,] "strD" "strE" "strF"
   [3,] "strG" "strI" "strJ"

        [,1]   [,2]   [,3]  
   [1,] "strA" "strB" "strC"
   [2,] "strE" "strF" "strG"
   [3,] "strH" "strI" "strJ"
...

有人对此有解决方案吗? 如果我的解释不清楚,请告诉我。

干杯

将假定转置组合矩阵命名为 mat。检查 intersect 函数的结果是否与长度重叠:

 res <- list();
 for (i in 1:nrow(mat) ){
    for( j in 1:nrow(mat)){  
          if( !length(intersect(mat[i,] , mat[j,])) ) 
               res[[paste(i,j,sep="_")]] <- rbind( mat[i,], mat[j, ]) } }


> res
$`1_20`
     [,1]   [,2]   [,3]  
[1,] "strA" "strB" "strC"
[2,] "strD" "strE" "strF"

$`2_19`
     [,1]   [,2]   [,3]  
[1,] "strA" "strB" "strD"
[2,] "strC" "strE" "strF"

$`3_18`
     [,1]   [,2]   [,3]  
[1,] "strA" "strB" "strE"
[2,] "strC" "strD" "strF"

.... snipped

根据您对 "unique" 的定义,您可能决定只取前十项,因为其中一半是行的换位:

> res[[1]]
     [,1]   [,2]   [,3]  
[1,] "strA" "strB" "strC"
[2,] "strD" "strE" "strF"
> res[[20]]
     [,1]   [,2]   [,3]  
[1,] "strD" "strE" "strF"
[2,] "strA" "strB" "strC"

在 42 的帮助下(再次感谢!)我想出了一个方法,虽然不优雅,但可以完成工作(慢慢...)。但只是因为我可以在执行以下步骤之前消除一些可能的组合,所以这种方式是可行的。在我最初的问题中,我有 49 个字符串,这会导致 非常大的向量,因此在将以下步骤应用于超过 15 个字符串时要小心 。肯定有一种方法可以计算必须处理多少组合...

完整示例来了

require(utils)
mylist<-paste("str",LETTERS[1:10],sep="")
mat<-as.data.frame(t(combn(mylist, 3, simplify = TRUE)))
mat[] <- lapply(mat, as.character)

mat.subset<-list()
for (i in seq(nrow(mat)))
{
  mat.temp<-mat
  j=1
  mat.subset[[i]]<-mat[i,]
  rem.row<-sort(unique(c(which(mat.temp[,1]%in%mat[i,1:3]),which(mat.temp[,2]%in%mat[i,1:3]),which(mat.temp[,3]%in%mat[i,1:3]))))
  mat.temp<-mat.temp[-rem.row,]
  while (j<=nrow(mat.temp))
  {
    if(!length(intersect(mat.temp[j,1:3],unlist(mat.subset[[i]]))))
    {
      mat.subset[[i]]<-rbind(mat.subset[[i]],mat.temp[j,])
      rem.row<-sort(unique(c(which(mat.temp[,1]%in%mat.temp[j,1:3]),which(mat.temp[,2]%in%mat[i,1:3]),which(mat.temp[,3]%in%mat[i,1:3]))))
      mat.temp<-mat.temp[-rem.row,]
    }
    j<-j+1
  }
}
mat.subset.lengths<-unlist(lapply(mat.subset,function(x) nrow(x)))
mat.subset<-mat.subset[which(mat.subset.lengths==max(mat.subset.lengths))]

在我的案例中,最后两个步骤是必要的,因为如上所述,我在耗时的 for 循环之前排除了一些组合,并且只有一定数量的起点才能产生完整的解决方案(或者在最坏的情况下接近完整的解决方案)。

如果您有提示说集合比此过程涵盖的更多,或者如果您有更优雅的方法,我将不胜感激。