【问题标题】:Error using optim() in purrr(): vmmin is not finite在 purrr() 中使用 optim() 时出错:vmmin 不是有限的
【发布时间】:2020-09-06 14:38:33
【问题描述】:

我从另一个工人那里收到了一个函数,用于计算一棵树在 100 岁 (SI) 时达到特定高度所需的高度。我的工作是将其放入 purrr 中,以计算一些 SI 和高度交叉点的高度,以绘制增长轨迹。

首先我创建基础函数:

SI_tall <- function(topheight,  age, si ){
  paramasi <- 25
  parambeta <- 7395.6
  paramb2 <- -1.7829
  refAge <- 100

  d <- parambeta*(paramasi^paramb2)

  r <- (((topheight-d)^2)+(4*parambeta*topheight*(age^paramb2)))^0.5

  ## height at reference age
  h2 <- (topheight+d+r)/ (2+(4*parambeta*(refAge^paramb2)) / (topheight-d+r))

  return(abs(h2 - si))
}

要计算给定年龄和站点索引的树的高度,我们在另一个中使用此函数。高度将由

给出
my.age  <- 10
my.si <- 30

new.topheight <- function(my.si, my.age){
  optim(par = list(topheight = 10), ## this topheight is just an initial value
                       method = 'L-BFGS-B', fn = SI_tall, si = my.si, age = my.age, lower= 0, upper=100)$par
}

这适用于每个值。 由于我想绘制每棵树的生长轨迹,我首先需要以所需的分辨率计算年龄和站点索引以进行绘图。我创建了两个要交叉的向量:

my.age <- seq(0,110, by=0.2)
my.si <- c(5,10,15,20,25,30,35)

si.crossing <- tidyr::crossing(my.age, my.si)

si.crossing %>% group_by(my.age, my.si) %>% 
  nest() %>%
  mutate(topheight = map2(.x=my.age, .y=my.si, .f=~new.topheight(my.si=.y, my.age=.x)))

这是我得到的错误:

优化错误(par = list(topheight = 30), method = "BFGS", fn = SI_tall, : 'vmmin' 中的初始值不是有限的

怎么了?非常感谢。

【问题讨论】:

    标签: r function dplyr tidyr purrr


    【解决方案1】:

    直接将其传递给map2_dbltryCatch 以处理错误。

    library(dplyr)
    library(purrr)
    
    si.crossing %>% 
         mutate(topheight = map2_dbl(my.si, my.age, 
                  ~tryCatch(new.topheight(.x, .y), error = function(e) NA)))
    

    或者在基础 R 中使用mapply

    si.crossing$topheight <- mapply(function(x, y) 
         tryCatch(new.topheight(x, y),error = function(e) NA), 
                  si.crossing$my.si, si.crossing$my.age)
    

    【讨论】:

    • 您好 Ronak,感谢您的回复!我的同事回答说优化启动参数有错误,我在上面的问题中进行了更改。但是,当我绘制您的解决方案时,new.topheight 使用年龄作为 SI,反之亦然 - 导致以下问题:new.topheight(my.si=100, my.age=15) -> 58.5 米。你知道为什么功能被颠倒了吗?我首先怀疑它按顺序填充了参数,所以我在 map2_dbl 调用中交换了 my.si 和 my.age 的位置。然而,这导致错误 L-BFGS-B 需要有限的 'fn' 值。非常感谢!
    • Ohhh...我看到我在map2_dbl 中颠倒了my.agemy.si 的值,但是如果我把它放在正确的位置它会返回一个错误。例如,看到这不起作用new.topheight(si.crossing$my.si[1], si.crossing$my.age[1]) 我不确定这里如何使用optim 函数,但可能有一些限制。
    • 我意识到我可以使用 safe_new.topheight
    • 我使用tryCatch 更新了答案以在返回错误时返回NA,看看是否有帮助。
    • 工作就像一个魅力!仍在尝试使用 safe() 解决它,但为此提出了另一个问题,因为它具有不同的兴趣。 stackoverflow.com/q/61917848/11550980
    【解决方案2】:

    我们可以从purrr使用possibly

    library(purrr)
    pnew.topheight <- possibly(new.topheight, otherwise = NA)
    si.crossing %>% 
        mutate(topheight = map2_dbl(my.si, my.age, pnew.topheight))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-26
      • 2021-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-28
      相关资源
      最近更新 更多