【问题标题】:R : How can I get all combinations from a bigger set to a smaller set?R:我怎样才能得到从一个更大的集合到一个更小的集合的所有组合?
【发布时间】:2015-12-28 11:53:53
【问题描述】:

我想知道是否有任何 R 包可以帮助我获得所有可能的 fusion 组合。 换句话说,我有一组 (1,2,3,4,5,6,7,8,9,10),我想得到一组 5 个子集,例如 (1,2,3 ,4,5,6),(7),(8),(9),(10) 或 (2,3,4,5,6),(1,7),(8),(9), (10) 或 (3,4,6) (1,5) (2,7) (9,10) (8) ...等 我设法编写了一个示例测试,但速度很慢:

library(partitions)
set = seq(1,10)
possibleCombinations = restrictedparts(10,5,include.zero = F)
fusionCombinations(set,possibleCombinations[,1],1,list())

fusionCombinations= function(set,setSize,i,prefix){
       o=combn(predicted,setSize[i])
       for(t in seq(1,ncol(o))){
        prefixtemp = prefix
        remaining = setdiff(predicted,o[,t])
        if(i+1<=length(setSize)){
          if(setSize[i+1]>1){
            prefixtemp=append(prefixtemp,list(o[,t]))
                result=append(result,fusionCombinations(remaining,setSize,i+1,prefixtemp))
          }else{
            prefixtemp=prefix
            prefixtemp=append(prefixtemp,list(o[,t]))
            prefixtemp=apply(t(remaining),1,append,prefixtemp)
            result=append(result,list(prefixtemp))
          }
        }
      }
      return(result)
    }

有什么想法吗?

【问题讨论】:

  • predicted 未定义。
  • 对不起,是的。预测代表集合
  • result 在定义之前使用。
  • 是的,例如可以是 list()
  • fusionCombinations 有一个参数 ii是什么意思?

标签: r combinations


【解决方案1】:

我的想法是使用setpartssplit

library(partitions)

f <- function(n,m)
{
  apply( setparts(restrictedparts(n,m,include.zero=FALSE)),
         2,
         function(k){split(1:n,k)})
}

例子:

> X <- f(4,3)
> X
[[1]]
[[1]]$`1`
[1] 1 4

[[1]]$`2`
[1] 2

[[1]]$`3`
[1] 3


[[2]]
[[2]]$`1`
[1] 1 2

[[2]]$`2`
[1] 3

[[2]]$`3`
[1] 4


[[3]]
[[3]]$`1`
[1] 1 3

[[3]]$`2`
[1] 2

[[3]]$`3`
[1] 4


[[4]]
[[4]]$`1`
[1] 2 4

[[4]]$`2`
[1] 1

[[4]]$`3`
[1] 3


[[5]]
[[5]]$`1`
[1] 2 3

[[5]]$`2`
[1] 1

[[5]]$`3`
[1] 4


[[6]]
[[6]]$`1`
[1] 3 4

[[6]]$`2`
[1] 1

[[6]]$`3`
[1] 2


> for ( i in 1:length(X) ) { prettyPrint(X[[i]]) }
[1] "(1, 4)( 2 )( 3 )"
[1] "( 1:2 )( 3 )( 4 )"
[1] "(1, 3)( 2 )( 4 )"
[1] "(2, 4)( 1 )( 3 )"
[1] "( 2:3 )( 1 )( 4 )"
[1] "( 3:4 )( 1 )( 2 )"
> 

.

> X <- f(5,2)
> X
[[1]]
[[1]]$`1`
[1] 1 2 4 5

[[1]]$`2`
[1] 3


[[2]]
[[2]]$`1`
[1] 1 2 3 5

[[2]]$`2`
[1] 4


[[3]]
[[3]]$`1`
[1] 1 2 3 4

[[3]]$`2`
[1] 5


[[4]]
[[4]]$`1`
[1] 1 3 4 5

[[4]]$`2`
[1] 2


[[5]]
[[5]]$`1`
[1] 2 3 4 5

[[5]]$`2`
[1] 1


[[6]]
[[6]]$`1`
[1] 1 2 5

[[6]]$`2`
[1] 3 4


[[7]]
[[7]]$`1`
[1] 1 2 4

[[7]]$`2`
[1] 3 5


[[8]]
[[8]]$`1`
[1] 1 2 3

[[8]]$`2`
[1] 4 5


[[9]]
[[9]]$`1`
[1] 1 3 5

[[9]]$`2`
[1] 2 4


[[10]]
[[10]]$`1`
[1] 1 3 4

[[10]]$`2`
[1] 2 5


[[11]]
[[11]]$`1`
[1] 1 4 5

[[11]]$`2`
[1] 2 3


[[12]]
[[12]]$`1`
[1] 2 3 5

[[12]]$`2`
[1] 1 4


[[13]]
[[13]]$`1`
[1] 2 3 4

[[13]]$`2`
[1] 1 5


[[14]]
[[14]]$`1`
[1] 2 4 5

[[14]]$`2`
[1] 1 3


[[15]]
[[15]]$`1`
[1] 3 4 5

[[15]]$`2`
[1] 1 2


> for ( i in 1:length(X) ) { prettyPrint(X[[i]]) }
[1] "(1, 2, 4, 5)( 3 )"
[1] "(1, 2, 3, 5)( 4 )"
[1] "( 1:4 )( 5 )"
[1] "(1, 3, 4, 5)( 2 )"
[1] "( 2:5 )( 1 )"
[1] "(1, 2, 5)( 3:4 )"
[1] "(1, 2, 4)(3, 5)"
[1] "( 1:3 )( 4:5 )"
[1] "(1, 3, 5)(2, 4)"
[1] "(1, 3, 4)(2, 5)"
[1] "(1, 4, 5)( 2:3 )"
[1] "(2, 3, 5)(1, 4)"
[1] "( 2:4 )(1, 5)"
[1] "(2, 4, 5)(1, 3)"
[1] "( 3:5 )( 1:2 )"
> 

函数prettyPrint

prettyPrint <- function(x)
{
  s <- ""

  for ( i in 1:length(x) )
  {
    p <- as.character(x[i])

    if ((nchar(p)==1) || (length(grep(":",p)>0)) )
    { s <- paste0(s,"( ",p," )")} else
    { s <- paste0(s,substr(p,2,nchar(p))) }

  }

  print(s)
}

.

【讨论】:

  • 好的,谢谢!它工作正常。但它仍然很慢:/
  • 在问题中,您提到了将 1:10 分解为 5 个不相交子集的示例。有 42525 个这样的分解。 Marat Talipov 接受的解决方案仅找到其中的 126 个,并且因此非常快。例如,问题中明确提到的分解 (3,4,6) (1,5) (2,7) (9,10) (8) 缺失。此外,Matteo Felici 的 (+1) 解决方案根本不起作用。什么更重要,速度还是正确性?请重新审视你的判断。
  • 啊,好吧,我的错!谢谢你的评论。我取消标记 Marat Talipov 的答案是正确的。我知道 Matteo Felici 不工作,但我同意你的是正确的!
【解决方案2】:

该函数以向量和样本个数为输入,然后找到nSets-1个随机切割(强制最后一个到向量的最后一个元素),然后依次打印向量的子集。

subsets <- function(vector, nSets) {
    cuts <- sample(1:(length(vector)-1), nSets-1, replace = F)
    cuts <- c(0,sort(cuts),length(vector))
    for (i in 1:nSets) {
        print(vector[(cuts[i]+1):cuts[i+1]])
    }
}

它也可以与非数值向量一起使用。

【讨论】:

  • 你的函数不是递归的。它提供了一种组合,但不是全部
【解决方案3】:

以下函数基于 Petr Savicky 于 2012 年 7 月 20 日发给 R-help [link] 的方法。

allcombs <- function(num, from=0, to=num) {
    m <- as.matrix(expand.grid(rep(list(0:1), times = num)))
    n.items <- rowSums(m)
    m[n.items >= from & n.items <= to, ]
}

在您的示例中,您将使用语句

allcombs(10, from=1, to=5)

获取大小为 1 到 5 的所有 637 个可能的子集。返回值是一个矩阵,其中行对应于每个可能的组合,列对应于项目编号。

【讨论】:

  • 我不确定这是我想要的。最后我需要 5 套,使用我们拥有的所有数字
  • 哦,是的,我明白了。我误解了您要查找的内容。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-05
相关资源
最近更新 更多