【问题标题】:R identify the variables which values sums a specific amountR识别变量的值总和特定数量
【发布时间】:2018-01-03 17:01:12
【问题描述】:

我有一个这样的 df:

       Client.Code.      Invoice        Amount 
   1:      1004772    20170800563       3620.32
   2:      1005012    20171000389       52661.62
   3:      1005012    20171000466       14800.72
   4:      1004742    20171200022       5445.00
   5:      1004724    20171100426       26620.00

然后我收到(例如)客户 1005012 支付 67462,34 的款项。在这种情况下,知道这笔款项与发票 20171000389 和 20171000466 相关是很简单的,但有时可能真的很难。

我想知道 R 中是否有任何方法可以识别变量之和等于给定数字的变量,并应用所有变量应来自同一客户端代码的限制。

谢谢。

【问题讨论】:

  • 您似乎在重新描述knapsack problem。在一般情况下,没有简单的方法可以解决这样的问题。
  • 这显然仍然是一个优化问题。它可能看起来“显而易见”且微不足道,只需检查几行即可,在这种情况下,您建议进行 per-client-id 详尽搜索。该解决方案在技术上是“NP-hard”。尤其是当 OP 说 “有时可能真的很难” 时,这证实了在 R 中执行此操作可能需要很长时间。 (顺便说一句:R FAQ 7.31 使用浮点比较可能会加剧这种情况,因此要找到正确的子集,您需要两个不等式约束。)
  • (我发誓刚才这里还有一条评论……)
  • 好的,我明白了,用 excel 的求解器很容易做到这一点,我会继续这样做。
  • Álvaro,不要误会我们在说什么。这在 R 中使用优化函数并不难实现,但很难概括,因为它是动态的和 NP 难的。 Excel 提供了一个用于设置基本优化类操作的 gui,但以编程方式解决它需要一些工作。快速搜索找到rdocumentation.org/packages/adagio/versions/0.6.5/topics/…

标签: r optimization solver


【解决方案1】:

这是在树中进行的搜索,它可能非常大(即使使用修剪)。 在这种情况下,剪枝意味着如果你已经有一个大于你想要的总和的值,那么继续在分支中搜索是没有用的。 你可以像这样实现这个搜索:

library(data.tree)

find_solutions <- function(df, client.code, sum.value, print_tree = FALSE) {

  df_sub <- subset(df, Client.Code. == client.code)
  # Sorting makes pruning better
  df_sub <- df_sub[order(df_sub$Amount, decreasing = TRUE), ]
  n <- nrow(df_sub)
  max <- sum.value
  solutions <- list()

  grow_tree <- function(node) {

    id <- node$level
    if (id <= n) {          
      val <- node$value + df_sub$Amount[id]
      if (val == max) {
        solutions[[length(solutions) + 1]] <<- 
          c(which(node$path[-1] == "yes"), id)
        node$AddChild("yes", value = val)
      } else if (val < max) {
        grow_tree(node$AddChild("yes", value = val))
        grow_tree(node$AddChild("no", value = node$value))
      } else {
        grow_tree(node$AddChild("no", value = node$value))
      }
    }

    NULL
  }

  grow_tree(root <- Node$new(value = 0))

  if (print_tree) print(root, "value")

  lapply(solutions, function(ids) df_sub$Invoice[ids])
}

测试:

# Your example data
df <- read.table(text = "       Client.Code.      Invoice        Amount 
   1:      1004772    20170800563       3620.32
           2:      1005012    20171000389       52661.62
           3:      1005012    20171000466       14800.72
           4:      1004742    20171200022       5445.00
           5:      1004724    20171100426       26620.00")


find_solutions(df, client.code = 1005012, sum.value = 67462.34, print_tree = TRUE)

df2 <- df
df2$Client.Code. = 1005012  
find_solutions(df2, client.code = 1005012, sum.value = 67462.34, print_tree = TRUE)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 2018-04-16
    • 2021-09-27
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    相关资源
    最近更新 更多