【问题标题】:Saving recursive function results to a global data frame in R将递归函数结果保存到 R 中的全局数据框
【发布时间】:2020-04-26 10:49:46
【问题描述】:

我试图通过将递归函数的输出保存在数据框中来重新创建基础 R 中的 memoise 包的功能。我有这个函数“P”,然后我制作了这个“metaP”包装器,如果之前没有运行过 metaP(n),它将运行 P(n),然后保存 P(n) 的结果,或者它产生以前的保存的输出。我的问题是它只适用于第一级。如果我运行 metaP(5),它将保存 metaP(5) 的输出,但为了得到 P(5),它还必须计算 P(4),并且 P(4) 的结果没有得到保存。我假设它在递归环境中丢失了,但是当我尝试使用 assign 函数并将其设置为全局环境时,它仍然不起作用。

在下面的示例中,我运行 metaP 5 到 10,df 保存了 5 到 10,但它没有保存 1 到 5,其中一些必须经过计算才能得出 5 到 10 的答案10.

df <- data.frame(n = 0, pn = 1)  

metaP <- function(n) {
  if (!n %in% df$n) df <<- rbind(df, data.frame(n = n, pn = P(n)))
  df[df$n == n, "pn"]
}

P <- function(n) {
  if (n < 0) return(0)
  k <- rep(1:((sqrt(24 * n + 1) + 1) / 6), each = 2) * c(1, -1)
  return(sum((-1) ^ (k + 1) * sapply(n - k * (3 * k - 1) / 2, metaP)) %% 1e6)
}

sapply(5:10, metaP)
df

【问题讨论】:

  • 将所有数据帧保存到一个列表中,然后执行:do.call("rbind", mylist) 以获得组合数据帧?

标签: r


【解决方案1】:

这里的问题有点微妙。表达式

df <<- rbind(df, data.frame(n = n, pn = P(n)))

是模棱两可的,因为?rbind 文档没有定义评估rbind() 的两个参数的顺序。 R 似乎正在评估df,然后进行递归调用,然后将该结果附加到df 的保存值。在递归调用期间对全局变量所做的任何更改都将丢失。

要解决这个问题,请将条件部分重写为

if (!n %in% df$n) {
  newval <- data.frame(n = n, pn = P(n))
  df <<- rbind(df, newval)
}

(我还建议在测试中添加括号,并将其写为if (!(n %in% df$n)),因为它们并不相同。我在之前对这个问题的回答中对此感到困惑。但是检查@ 987654328@ 表示%in% 的优先级高于!。)

【讨论】:

  • 有道理!至于错字,我记得在 R Inferno 中读到 !n %in% df$n!(n %in% df$n) 以相同的方式评估,即使第一个看起来不应该。我再次和他们一起玩,看起来他们总是以同样的方式评估。
猜你喜欢
  • 2020-07-29
  • 1970-01-01
  • 1970-01-01
  • 2020-02-02
  • 2019-07-28
  • 2014-01-17
  • 2014-04-08
  • 2019-08-30
  • 2017-08-11
相关资源
最近更新 更多