用r中的置换填充数据集

时间:2019-02-10 19:42:30

标签: r permutation

我是r的新手。我需要用置换填充数据集。我为小型数据集创建了一个,其中有4列(插槽),可以用0到8之间的任何数字填充。它们的总和应等于6。

我需要对较大的集合进行处理,其中column(slots = 6)和sequence为1到200,所需的总和为100。根据上述脚本,这花费了太多时间。请提出另一种方法。

谢谢。

library(gtools)
library(dplyr)

df <- as.data.frame( permutations(5,4,seq(0,8,1))) %>% 
  mutate(sum = `V1`+`V2`+`V3`+`V4`) %>% 
  filter(sum == 6) %>% 
  select(-sum)

2 个答案:

答案 0 :(得分:1)

一个选项是:

as.data.frame(permutations(5, 4, seq(0, 8, 1))) %>% 
  filter(reduce(., `+`) == 6)

另一方面,这也可以在dplyr或其他包之外进行,例如:

df <- as.data.frame(permutations(5, 4, seq(0, 8, 1)))

df[reduce(df, `+`) == 6,]

您也可以尝试data.table,例如:

library(data.table)

dt <- setDT(as.data.frame(permutations(5, 4, seq(0, 8, 1))))

dt[Reduce(`+`, mget(names(dt))) == 6]

或者也可以是另一种选择-可能更慢-(在如上所述保存到dt之后):

dt[dt[, rowSums(.SD) == 6]]

答案 1 :(得分:1)

使用RcppAlgos(我是作者),这很简单。

RcppAlgos::permuteGeneral(seq(0, 8, 1), 4,
                          constraintFun = "sum",
                          comparisonFun = "==",
                          limitConstraints = 6)

下面的算法经过优化,可以快速删除不可能的解决方案。我们也只考虑检查组合,因为加法/乘法是可交换的,顺序无关紧要。一旦找到合适的组合,我们就会生成该特定组合的所有排列。这也有助于我们将Rcpp用于提高效率。

对于具有200个数字和6列的OP的现实世界问题,可行性将在很大程度上取决于所需的总和。如果我们考虑了平均总和(将最多),则可能需要考虑其他方法,因为可能的解决方案的剪切数超过了2^31 - 1。这也将花费大量时间。仅用5列和500的总和,我什至无法产生排列。但是,我可以产生组合:

res <- RcppAlgos::comboGeneral(1:200, 5,
                               constraintFun = "sum",
                               comparisonFun = "==",
                               limitConstraints = 500, 
                               upper = 1e8)  ## upper argument constrains the output to a maximum number of results
nrow(res)
[1] 7669861

鉴于没有重复,我们可以计算出排列的数量:

  

7669861 *阶乘(5)= 920,383,320

这是我得到的错误:

res <- RcppAlgos::permuteGeneral(1:200, 5,
                                constraintFun = "sum",
                                comparisonFun = "==",
                                limitConstraints = 500, 
                                upper = 921000000)
Show Traceback

Rerun with Debug
Error: vector memory exhausted (limit reached?) 

如果所需的总和与平均总和相比相对较小或较大,则可以进行计算。例如,如果期望的总和为100,我们可以快速获得所有排列:

system.time(res <- RcppAlgos::permuteGeneral(1:200, 6,
                                             constraintFun = "sum",
                                             comparisonFun = "==",
                                             limitConstraints = 100, 
                                             upper = 1e8))
 user  system elapsed 
2.213   0.525   2.753 

nrow(res)
[1] 47395440