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
循环之前排除了一些组合,并且只有一定数量的起点才能产生完整的解决方案(或者在最坏的情况下接近完整的解决方案)。
如果您有提示说集合比此过程涵盖的更多,或者如果您有更优雅的方法,我将不胜感激。
不确定我是否选择了一个好的标题...我也不知道我是否使用了正确的术语,所以也许使用正确的搜索词我会找到解决这个问题的方法...
我有一个字符串列表,我希望从中得到所有 "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
循环之前排除了一些组合,并且只有一定数量的起点才能产生完整的解决方案(或者在最坏的情况下接近完整的解决方案)。
如果您有提示说集合比此过程涵盖的更多,或者如果您有更优雅的方法,我将不胜感激。