我是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)
一种选择是:
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]]
使用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