r - 使用总和约束生成排列
问题描述
我有n
一组可变长度,并希望从总和在一定范围内的每个集合中获取项目的所有排列。例如,R
我们可以这样做:
set1 <- c(10, 15, 20)
set2 <- c(8, 9)
set3 <- c(1, 2, 3, 4)
permutations <- expand.grid(set1, set2, set3)
permutations$sum <- rowSums(permutations)
final <- permutations[permutations$sum >= 25 & permutations$sum <= 29, ]
# final:
# Var1 Var2 Var3 sum
# 3 20 8 1 29
# 5 15 9 1 25
# 8 15 8 2 25
# 11 15 9 2 26
# 14 15 8 3 26
# 17 15 9 3 27
# 20 15 8 4 27
# 23 15 9 4 28
这对于少量集合来说很好,但是随着集合数量的增加或增加而快速(因子)增长。
是否可以生成符合约束的排列,而无需计算所有可能性?
在此示例中,没有包含 10 的最终组合set1
,因为无论选择哪些其他数字,结果总和都会太小。这可能有助于缩小问题的范围。例如,如果我知道min(set1) + max(set2) + max(set3) < 25 == TRUE
,那么我可以确保不包含min(set1)
在任何排列中。
我怎样才能概括这一点,并使用约束来防止产生无效的排列?
解决方案
我认为您所要求的内容非常具体,不太可能“易于实施”(有效地)。另一种看待它的方法是在运行实验时进行调节(假设这是试验设计)。
我写了一个lazyExpandGrid.R
在概念上与lazy 相似的a expand.grid
,这意味着它不会预先评估所有可能的组合。如果需要,可以稍后在此答案中插入代码,但 github-gist 相当可靠(而且不短)。
使用它,您应该能够:
set1 <- c(10, 15, 20)
set2 <- c(8, 9)
set3 <- c(1, 2, 3, 4)
iter <- lazyExpandGrid(set1, set2, set3)
while (is.data.frame(item <- iter$nextItem())) {
p <- sum(item)
if (p < 25 || 29 < p) next
print(item) # but really, do something more interesting here
}
# Var1 Var2 Var3
# 3 20 8 1
# Var1 Var2 Var3
# 5 15 9 1
# Var1 Var2 Var3
# 8 15 8 2
# Var1 Var2 Var3
# 11 15 9 2
# Var1 Var2 Var3
# 14 15 8 3
# Var1 Var2 Var3
# 17 15 9 3
# Var1 Var2 Var3
# 20 15 8 4
# Var1 Var2 Var3
# 23 15 9 4
警告购买者:该功能大部分是可用的,但肯定有可以改进的方法。例如,使用is.data.frame(item <- iter$nextItem())
实际上是一个isTruthy
测试(名称来自shiny
);目前它返回一个 1 行data.frame
,直到什么都没有,然后返回FALSE
。当我现在看它时,这肯定可以改进,我只是没有需要。如果您有想法、错误等,请随时在 github gist 页面上发表评论。
推荐阅读
- powerbi - 如何在 Power BI 中将工作日转换为每天可以多次更新的小时?
- javascript - JSX 中的多个 if/else
- sql - Rmarkdown - 评估或显示 SQL 块的参数化查询
- python - 如何获取 WebElement 的值
- angular - 此客户端应用程序未批准回调 URL。可以在您的应用程序设置中调整已批准的回调 URL
- spring - 不将 EntityManager 标记为 @PersistenceContext 的含义是什么
- elasticsearch - Elasticsearch:在相关分数中使用密集向量的距离(在查询时)
- javascript - 如何使用 Firestore 查询为 javascript 执行基于用户角色的登录
- html - 如何为深色模式加载不同的视频
- python - 不知道这里发生了什么,没有打破循环