【问题标题】:R: Solving for a variable (using the uniroot function)R:求解变量(使用 uniroot 函数)
【发布时间】:2021-09-03 13:28:11
【问题描述】:

我对 R 比较陌生,确实需要社区的帮助来解决以下问题。我正在尝试求解以下等式中的变量 r:(EPS2 + r*DPS1-EPS1)/r^2)-PRC。这是我解决问题的(不成功的)尝试(使用 uniroot 函数):

EPS2 = df_final$EPS2

DPS1 = df_final$DPS1

EPS1 = df_final$EPS1

PRC = df_final$PRC

f1 = function(r) {
    ((df_final_test$EPS2 + r * df_final_test$DPS1-df_final_test$EPS1)/r^2)-df_final_test$PRC 
}

uniroot(f1,interval = c(1e-8,100000),EPS2, DPS1, EPS1, PRC , extendInt="downX")$root

然后我得到以下错误:f(lower, ...) 中的错误:未使用 参数(c(“1.39”,“1.39”,...

感谢你们就这个问题给我的任何提示和提示。或者在这种情况下,不同的功能/包是否会更好。

添加了一个代表 (?) 以防万一有人帮助我解决这个问题:

df <- structure(list(EPS1 = c(6.53, 1.32, 1.39, 1.71, 2.13), DPS1 = c(2.53, 0.63,
0.81, 1.08, 1.33, 19.8), EPS2 = c(7.57,1.39,1.43,1.85,2.49), PRC = c(19.01,38.27,44.82,35.27,47.12)), .Names = c("EPS1", "DPS1", "EPS2", "PRC"), row.names = c(NA,
-5L), class = "data.frame")

【问题讨论】:

  • 嗨,杰西卡,你能提供一个代表吗? (adv-r.had.co.nz/Reproducibility.html)
  • @MarceloAvila 已将其添加到帖子中。希望这可以帮助任何可以帮助我的人:)

标签: r equation-solving nonlinear-equation uniroot


【解决方案1】:

免责声明:我没有使用uniroot() 的经验,也不知道以下内容是否有意义,但它可以运行!这个想法基本上是为数据框的每一行调用uniroot

请注意,我稍微修改了函数f1,因此每个附加参数都必须作为函数的参数传递,而不是依赖于在父环境中查找具有相同名称的对象。我还使用with 来避免为每个变量调用df$...

library(tidyverse)
#> Warning: package 'ggplot2' was built under R version 4.1.0
library(furrr)
#> Loading required package: future


df <- structure(list(EPS1 = c(6.53, 1.32, 1.39, 1.71, 2.13),
                     DPS1 = c(2.53, 0.63, 0.81, 1.08, 1.33, 19.8),
                     EPS2 = c(7.57,1.39,1.43,1.85,2.49),
                     PRC = c(19.01,38.27,44.82,35.27,47.12)),
                .Names = c("EPS1", "DPS1", "EPS2", "PRC"),
                row.names = c(NA,-5L), class = "data.frame")
df
#> Warning in format.data.frame(if (omit) x[seq_len(n0), , drop = FALSE] else x, :
#> corrupt data frame: columns will be truncated or padded with NAs
#>   EPS1  DPS1 EPS2   PRC
#> 1 6.53  2.53 7.57 19.01
#> 2 1.32  0.63 1.39 38.27
#> 3 1.39  0.81 1.43 44.82
#> 4 1.71  1.08 1.85 35.27
#> 5 2.13  1.33 2.49 47.12

f1 = function(r, EPS2, DPS1, EPS1, PRC) {
  (( EPS2 + r *  DPS1 - EPS1)/r^2) - PRC 
}

# try for first row 
with(df, 
     uniroot(f1, 
             EPS2=EPS2[1], DPS1=DPS1[1], EPS1=EPS1[1], PRC=PRC[1],
             interval = c(1e-8,100000), 
             extendInt="downX")$root)
#> [1] 0.3097291
# it runs! 


# loop over each row
vec_sols <- rep(NA, nrow(df))
for (i in seq_along(1:nrow(df))) {
  
  sol <- with(df, uniroot(f1, 
                          EPS2=EPS2[i], DPS1=DPS1[i], EPS1=EPS1[i], PRC=PRC[i],
                          interval = c(1e-8,100000), 
                          extendInt="downX")$root)
  vec_sols[i] <- sol
}
vec_sols
#> [1] 0.30972906 0.05177443 0.04022946 0.08015686 0.10265226


# Alternatively, you can use furrr's future_map_dbl to use multiple cores.
# the following will basically do the same as the above loop. 
# here with 4 cores. 
plan(multisession, workers = 4)
vec_sols <- 1:nrow(df) %>% furrr::future_map_dbl(
  .f = ~with(df, 
             uniroot(f1, 
                     EPS2=EPS2[.x], DPS1=DPS1[.x], EPS1=EPS1[.x], PRC=PRC[.x],
                     interval = c(1e-8,100000), 
                     extendInt="downX")$root
  ))
vec_sols
#> [1] 0.30972906 0.05177443 0.04022946 0.08015686 0.10265226


# then apply the solutions back to the dataframe (each row to each solution)
df %>% mutate(
  root = vec_sols
)
#> Warning in format.data.frame(if (omit) x[seq_len(n0), , drop = FALSE] else x, :
#> corrupt data frame: columns will be truncated or padded with NAs
#>   EPS1  DPS1 EPS2   PRC       root
#> 1 6.53  2.53 7.57 19.01 0.30972906
#> 2 1.32  0.63 1.39 38.27 0.05177443
#> 3 1.39  0.81 1.43 44.82 0.04022946
#> 4 1.71  1.08 1.85 35.27 0.08015686
#> 5 2.13  1.33 2.49 47.12 0.10265226

reprex package (v2.0.0) 于 2021-06-20 创建

【讨论】:

    【解决方案2】:

    如果所有系数都是向量而不是标量,我认为您不能使用uniroot。在这种情况下,一种直接的方法是以数学方式解决它们,即,

    r1 <- (DPS1 + sqrt(DPS1^2-4*PRC*(EPS1-EPS2)))/(2*PRC)
    

    r2 <- (DPS1 - sqrt(DPS1^2-4*PRC*(EPS1-EPS2)))/(2*PRC)
    

    其中r1r2 是两个根。

    【讨论】:

    • 谢谢!我会试一下!我想知道是否还有另一种方法可以使用不同的包/函数而不是使用“数学方式”。我还需要对更复杂的方程使用相同的方法,其中以“数学方式”求解它们可能不是一种可行的方法。有什么建议吗?
    • @Jessica168 由于您尝试使用uniroot 求解向量r,因此您应该对函数进行向量化。也许你应该尝试uniroot element-wise,这样每次参数元组都会传递给uniroot。例如,我们从DPS1PRCEPS1EPS2中取出第k个值,并将它们传递给uniroot,得到r的第k个值。
    • 感谢您的意见@ThomasIsCoding!如果没有其他选项可用,我将尝试按元素的方法(我有 127834 个观察结果,因此我必须分别对它们中的每一个进行此操作,这将花费很长时间)。不过非常感谢!
    • @Jessica168 如果你可以手动求解,我会推荐数学方法,它会更快更精确。
    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 2022-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    • 1970-01-01
    相关资源
    最近更新 更多