选择列总和等于R中固定值的行
我想得到一个(或全部)行的可能组合,其中数量列的和等于20 这里有一个例子:选择列总和等于R中固定值的行,r,R,我想得到一个(或全部)行的可能组合,其中数量列的和等于20 这里有一个例子: structure(list(id = 1:10, quantity = c(11L, 1L, 4L, 12L, 19L, 10L, 3L, 13L, 16L, 14L)), class ="data.frame", row.names = c(NA,-10L)) id quantity 1 11 2 1 3 4 4 12
structure(list(id = 1:10, quantity = c(11L, 1L, 4L, 12L, 19L, 10L, 3L, 13L, 16L, 14L)), class ="data.frame", row.names = c(NA,-10L))
id quantity
1 11
2 1
3 4
4 12
5 19
6 10
7 3
8 13
9 16
10 14
所需输出(一个可能的设置):
或
如果组合正常:
target <- 20
lapply(seq_len(sum(cumsum(sort(x$quantity)) <= target)), function(n) {
y <- combn(x$quantity, n)
y[,colSums(y) == target]
})
#[[1]]
#integer(0)
#
#[[2]]
# [,1] [,2]
#[1,] 1 4
#[2,] 19 16
#
#[[3]]
# [,1] [,2]
#[1,] 1 4
#[2,] 3 3
#[3,] 16 13
#
#[[4]]
#[1] 1 4 12 3
target这里是另一个基本的R解决方案,通过定义一个递归函数子函数(我想这会更快,因为它避免了检查所有的组合)
如果您只需要达到给定值的子集和中的一个,您可以尝试从packageadagio
library(adagio)
target <- 20
res <- df[subsetsum(df$quantity,target)$inds,]
您可以添加失败的内容吗?关于这些组合有哪些规则?没有固定的规则,我只需要满足sum(quantity)==20See的任何组合,以及如何获取相关ID?我已经进行了更新,返回了行-如最初所问。我喜欢您的解决方案,如何使它在满足求和条件的第一个组合处停止循环?我在if语句中添加了一个break指令,但它不起作用(我必须循环3000个产品,每个产品至少有长度为100的quantity数组)@Seif我认为您无法进入递归并提取第一个组合。相反,您可以使用packageadagio
中的函数subsetsum
来创建它。查看我的更新。
target <- 20
lapply(seq_len(sum(cumsum(sort(x$quantity)) <= target)), function(n) {
y <- combn(x$quantity, n)
y[,colSums(y) == target]
})
#[[1]]
#integer(0)
#
#[[2]]
# [,1] [,2]
#[1,] 1 4
#[2,] 19 16
#
#[[3]]
# [,1] [,2]
#[1,] 1 4
#[2,] 3 3
#[3,] 16 13
#
#[[4]]
#[1] 1 4 12 3
lapply(seq_len(sum(cumsum(sort(x$quantity)) <= target)), function(n) {
y <- combn(x$quantity, n)
y <- y[,colSums(y) == target, drop = FALSE]
if(length(y) > 0) {apply(y, 2, match, x$quantity)}
})
#[[1]]
#NULL
#
#[[2]]
# [,1] [,2]
#[1,] 2 3
#[2,] 5 9
#
#[[3]]
# [,1] [,2]
#[1,] 2 3
#[2,] 7 7
#[3,] 9 8
#
#[[4]]
# [,1]
#[1,] 2
#[2,] 3
#[3,] 4
#[4,] 7
lapply(seq_len(sum(cumsum(sort(x$quantity)) <= target)), function(n) {
y <- combn(x$quantity, n)
y <- y[,colSums(y) == target, drop = FALSE]
if(length(y) > 0) {apply(y, 2, function(i) {x[match(i, x$quantity),]})}
})
#[[1]]
#NULL
#
#[[2]]
#[[2]][[1]]
# id quantity
#2 2 1
#5 5 19
#
#[[2]][[2]]
# id quantity
#3 3 4
#9 9 16
#
#
#[[3]]
#[[3]][[1]]
# id quantity
#2 2 1
#7 7 3
#9 9 16
#
#[[3]][[2]]
# id quantity
#3 3 4
#7 7 3
#8 8 13
#
#
#[[4]]
#[[4]][[1]]
# id quantity
#2 2 1
#3 3 4
#4 4 12
#7 7 3
x <- structure(list(id = 1:10, quantity = c(11L, 1L, 4L, 12L, 19L, 10L, 3L, 13L, 16L
, 14L)), class ="data.frame", row.names = c(NA,-10L))
subsetSum <- function(v, target, r = c()) {
if (sum(r) == target) {
return(list(r))
}
unlist(lapply(seq_along(v), function(k) subsetSum(v[-(1:k)], target, c(r, v[k]))), recursive = FALSE)
}
target <- 20
lst <- subsetSum(setNames(df$quantity, seq(nrow(df))), target)
res <- Map(function(v) df[as.integer(names(v)), ], lst)
> res
[[1]]
id quantity
2 2 1
3 3 4
4 4 12
7 7 3
[[2]]
id quantity
2 2 1
5 5 19
[[3]]
id quantity
2 2 1
7 7 3
9 9 16
[[4]]
id quantity
3 3 4
7 7 3
8 8 13
[[5]]
id quantity
3 3 4
9 9 16
library(adagio)
target <- 20
res <- df[subsetsum(df$quantity,target)$inds,]
> res
id quantity
2 2 1
5 5 19