如何在 R 中迭代地产生组合? [复制]

Posted

技术标签:

【中文标题】如何在 R 中迭代地产生组合? [复制]【英文标题】:How to produce combinations iteratively in R? [duplicate] 【发布时间】:2013-07-15 00:53:15 【问题描述】:

所以我目前正在使用以下代码来生成我的组合:

combn(x,y)

但问题是函数存储了所有可能的组合。我不想存储它们,我只想像循环或其他东西一样生产它们。这对我的程序来说会更有效率。有没有办法通过 for 循环生成组合而不是全部存储?

我知道我在这里问了一个类似的问题: How do I find all possible subsets of a set iteratively in R?

但在那个解决方案中,组合仍然被存储......

这里有更多细节:

假设我想找到 4 选择 2。combn(4,2) 基本上会存储以下内容: ((1,4),(1,3),(1,2),(2,4),(2,3)(3,4))

我想要的是这个:

   loop
       produces one combination at a time 
   

【问题讨论】:

是的,但在那个答案中,组合仍在存储中 什么意思?它们是如何存储的? 我认为 OP 在这里想要的是一个函数,它不仅输出所有可能的组合,而且需要一个额外的变量,比如i,它得到第 i 个值 combn(x,y)。虽然function(x,y,i)combn(x,y)[i] 在技术上可行,但效率不高。 不确定这是否适用,但通常 data.table 有助于提高性能:***.com/questions/16919998/… 也许你在rosettacode找到一个算法 【参考方案1】:

这是一个建议,它允许根据循环的前一次迭代中使用的组合为循环的当前迭代生成组合。

## Function definition
gen.next.cbn <- function(cbn, n)
    ## Generates the combination that follows the one provided as input
    cbn.bin      <- rep(0, n)
    cbn.bin[cbn] <- 1
    if (tail(cbn.bin, 1) == 0)
        ind <- tail(which(cbn.bin == 1), 1)
        cbn.bin[c(ind, ind+1)] <- c(0, 1)
    else
        ind <- 1 + tail(which(diff(cbn.bin) == -1), 1)
        nb  <- sum(cbn.bin[-c(1:ind)] == 1)
        cbn.bin[c(ind-1, (n-nb+1):n)] <- 0
        cbn.bin[ind:(ind+nb)]         <- 1
    
    cbn <- which(cbn.bin == 1)


## Example parameters
n   <- 6
k   <- 3

## Iteration example
for (i in 1:choose(n, k))
    if (i == 1)
        cbn <- 1:k
    else
        cbn <- gen.next.cbn(cbn, n)
    
    print(cbn)


# [1] 1 2 3
# [1] 1 2 4
# [1] 1 2 5
# [1] 1 2 6
# [1] 1 3 4
# [1] 1 3 5
# [1] 1 3 6
# [1] 1 4 5
# [1] 1 4 6
# [1] 1 5 6
# [1] 2 3 4
# [1] 2 3 5
# [1] 2 3 6
# [1] 2 4 5
# [1] 2 4 6
# [1] 2 5 6
# [1] 3 4 5
# [1] 3 4 6
# [1] 3 5 6
# [1] 4 5 6

【讨论】:

@user2560984,这对你有用吗?【参考方案2】:

如果目标是将每个组合用作某些计算的输入,您可能希望使用combnFUN 参数,例如apply。这似乎不会存储组合,但仍会立即返回应用于每个组合的函数的结果。

这是一个带有虚拟函数的示例:

fct <- function(x, y)sum(x*y) + 2*x[1]
y   <- 1:5
system.time(combn(1:20, 5, fct, y = y))
# user  system elapsed 
# 0.160   0.000   0.161 
system.time(apply(combn(1:20, 5), 2, fct, y = y))
# user  system elapsed 
# 0.224   0.000   0.222 

【讨论】:

我在我的问题中添加了更多细节。 这将是最好的解决方案,假设您想要捕获每个返回值。否则,为什么不查看combn 的代码并根据您的需要进行调整?【参考方案3】:

要循环返回每个可能的组合,一次一个,执行以下操作:

#Sample data:
x <- c(1,2,3,4)
y <- 2
all_combinations <- combn(x,y)

#Return each value:
for (i in 1:ncol(all_combinations)) 
  print(all_combinations[,i])

但我不确定为什么要在 for 循环中执行此操作,因为它非常慢。除了这个应用程序之外,还有期望的最终输出吗?

【讨论】:

我在我的问题中添加了更多细节。 感谢您提供详细信息。那么,这个答案应该对你有用。例如,sample(1:4,2) 我认为这行不通,因为它会随机生成每个组合,对吧? 啊,@user2560984。查看更新。 但是你存储的值是我不想要的......

以上是关于如何在 R 中迭代地产生组合? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在 R 中迭代地过滤列表中的列表或如何同时使用两个条件过滤 data.table,在运行时创建对象

如何快速(优雅地)在 R 中的时间序列对象 `ts` 和日期框架之间进行迭代以进行 ggplot2 绘图?

如何在 R 中的单个数据帧上迭代地应用函数?

如何迭代地将 2 个列表中的元素应用到新函数中? [复制]

如何迭代地将参数传递给 R 函数

如何在较大的数据集上迭代执行组合?