在r中使用Permutation填充数据集

问题描述 投票:1回答:2

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

我需要做更大的集合,其中列(插槽= 6)和序列是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)
r permutation
2个回答
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
投票

使用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 * factorial(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
© www.soinside.com 2019 - 2024. All rights reserved.