You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R中检测数字集合能否求和至指定值的标准方法问询

问题描述

我有如下数据框:

set.seed(123)
random_table <- data.frame(
  Column1 = sample(1:10, 5, replace = TRUE),
  Column2 = sample(1:10, 5, replace = TRUE),
  Column3 = sample(1:10, 5, replace = TRUE),
  Column4 = sample(1:10, 5, replace = TRUE),
  Column5 = sample(1:10, 5, replace = TRUE)
)

数据框内容:

Column1 Column2 Column3 Column4 Column5
       3       5       5       3       9
       3       4       3       8       3
      10       6       9      10       4
       2       9       9       7       1
       6      10       9      10       7

我希望编写一个函数,检测该数据框中选取n个数字能否求和得到指定值m,若可行则记录所有符合条件的组合(包含对应单元格位置),否则返回NULL。

我尝试使用combinat包编写了如下函数:

library(combinat)

find_combinations <- function(table, num, target_sum) {

    combinations <- combn(as.vector(as.matrix(table)), num)

    valid_combinations <- list()
    valid_cells <- list()

    for (i in 1:ncol(combinations)) {
        if (sum(combinations[, i]) == target_sum) {
            valid_combinations <- append(valid_combinations, list(combinations[, i]))
        
            cells <- c()
            for (value in combinations[, i]) {
            cell <- which(table == value, arr.ind = TRUE)[1, ]
            cells <- c(cells, paste0(LETTERS[cell[2]], cell[1]))
        }
        valid_cells <- append(valid_cells, list(cells))
    }
}

if (length(valid_combinations) > 0) {
    result <- data.frame(
        id = seq_along(valid_combinations),
        sum = rep(target_sum, length(valid_combinations)),
        numbers_selected = sapply(valid_combinations, function(x) paste(x, collapse = ",")),
        cells = sapply(valid_cells, function(x) paste(x, collapse = ","))
    )
} else {
    result <- data.frame(
        id = NA,
        sum = NA,
        numbers_selected = NA,
        cells = NA
    )
}

return(result)
}

随后我调用该函数并移除了cells列相关的重复项:

result <- find_combinations(random_table, num = 4, target_sum = 19)

result$sorted_cells <- sapply(strsplit(result$cells, ","), function(x) paste(sort(x), collapse = ","))
result <- result[!duplicated(result$sorted_cells), ]
result$sorted_cells <- NULL

result$id <- seq_len(nrow(result))

输出结果如下:

id sum numbers_selected       cells
  1  19         3,3,10,3 A1,A1,A3,A1
  2  19          3,3,6,7 A1,A1,A5,D4
  3  19          3,3,5,8 A1,A1,B1,D2
  4  19          3,3,4,9 A1,A1,B2,B4
  5  19         3,10,2,4 A1,A3,A4,B2

请问在R中是否有实现该需求的标准方法,还是必须自行编写函数?


解答

在R里没有完全直接匹配这个需求的「标准函数」,但可以借助现有工具包简化实现,同时优化你当前代码里的问题(比如原代码中which(table == value, arr.ind = TRUE)[1, ]只会取第一个匹配值,会丢失其他可能的单元格位置,导致组合记录不全)。

优化思路与实现

  1. 先转长格式追踪位置:把数据框转换成包含值、行号、列名的长表,避免重复值导致的位置匹配错误。
  2. 基于位置生成组合:直接对每个元素的位置做组合筛选,再匹配对应的值求和,确保位置记录准确。
  3. 高效去重:直接基于排序后的位置组合去重,不用额外生成中间列。

示例优化代码:

find_combinations <- function(df, num, target_sum) {
    # 转换为长格式,记录每个值的单元格位置
    long_df <- data.frame(
        value = unlist(df),
        cell = paste0(LETTERS[col(df)], row(df)),
        stringsAsFactors = FALSE
    )
    
    # 生成所有num个元素的位置组合
    pos_combinations <- combn(1:nrow(long_df), num)
    
    # 筛选求和等于目标值的组合
    valid_idx <- apply(pos_combinations, 2, function(idx) sum(long_df$value[idx]) == target_sum)
    valid_pos <- pos_combinations[, valid_idx, drop = FALSE]
    
    if (ncol(valid_pos) == 0) {
        return(NULL)
    }
    
    # 整理结果并去重
    result_list <- apply(valid_pos, 2, function(idx) {
        cells <- long_df$cell[idx]
        sorted_cells <- sort(cells)
        list(
            sum = target_sum,
            numbers_selected = paste(long_df$value[idx], collapse = ","),
            cells = paste(cells, collapse = ","),
            sorted_cells = paste(sorted_cells, collapse = ",")
        )
    })
    
    result_df <- do.call(rbind.data.frame, result_list)
    # 去重并清理列
    result_df <- result_df[!duplicated(result_df$sorted_cells), ]
    result_df$sorted_cells <- NULL
    result_df$id <- seq_len(nrow(result_df))
    
    # 调整列顺序
    result_df <- result_df[, c("id", "sum", "numbers_selected", "cells")]
    return(result_df)
}

# 调用测试
result <- find_combinations(random_table, num = 4, target_sum = 19)
print(result)

可选工具包支持

  • 处理大数据量时,arrangements包的combinations函数比combinat包的combn性能更优;
  • 若只需判断是否存在解而非枚举所有组合,可以用lpSolve包做整数规划求解;
  • 追求极致效率的话,可结合Rcpp编写底层逻辑加速组合筛选。

内容的提问来源于stack exchange,提问作者farrow90

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 20:37:32