【问题标题】:How to compute double integral in r?如何计算r中的双积分?
【发布时间】:2020-09-06 03:29:34
【问题描述】:

假设我们有以下密度:

  bvtnorm <- function(x, y, mu_x = 10, mu_y = 5, sigma_x = 3, sigma_y = 7, rho = 0.4) {
    
    function(x, y) 
      1 / (2 * pi * sigma_x * sigma_y * sqrt(1 - rho ^ 2)) * 
      exp(- 1 / (2 * (1 - rho ^ 2)) * (((x - mu_x) / sigma_x) ^ 2 + 
                                         ((y - mu_y) / sigma_y) ^ 2 - 2 * rho * (x - mu_x) * (y - mu_y) / 
                                         (sigma_x * sigma_y)))
  }
  
  f2 <- bvtnorm(x, y)

我想计算以下积分:

integral_1=1-adaptIntegrate(f2, lowerLimit = c(-Inf,0), upperLimit = c(+Inf,+Inf))

不幸的是,它提供了这个错误:

Error in f(tan(x), ...) : argument "y" is missing, with no default

我不知道如何解决这个问题。 提前感谢您的帮助!

【问题讨论】:

  • bvtnorm 产生的函数f2 有两个参数,x 和 y,但是adaptIntegrate 需要一个单变量函数,所以它不能用于这边
  • @AllanCameron,我应该用 c(x,y) 更改 x,y 吗?
  • double integral in R 可能会有所帮助。

标签: r


【解决方案1】:

对于包cubature、函数hcubaturepcubature,被积函数必须稍作更改。该包中的积分器仅接受一个变量的被积函数,该变量可以是多维实空间中的向量。在这种情况下,R2。 xy 的值必须在被积函数中赋值,或者在其表达式中更改为 x[1]x[2]

bvtnorm <- function(x, mu_x = 10, mu_y = 5, sigma_x = 3, sigma_y = 7, rho = 0.4) {
  
  y <- x[2]
  x <- x[1]
  1 / (2 * pi * sigma_x * sigma_y * sqrt(1 - rho ^ 2)) * 
  exp(- 1 / (2 * (1 - rho ^ 2)) * (((x - mu_x) / sigma_x) ^ 2 + 
                                       ((y - mu_y) / sigma_y) ^ 2 - 2 * rho * (x - mu_x) * (y - mu_y) / 
                                       (sigma_x * sigma_y)))
}

library(cubature)

eps <- .Machine$double.eps^0.5
hcubature(bvtnorm, lowerLimit = c(-Inf, 0), upperLimit = c(+Inf,+Inf), tol = eps)
pcubature(bvtnorm, lowerLimit = c(-Inf, 0), upperLimit = c(+Inf,+Inf), tol = eps)

【讨论】:

  • 这个瑞不错。我不知道在问题中是否有意将积分下限设置为c(-Inf, 0),但如果将它们更改为c(-Inf, -Inf),则返回的积分正好为1,所以我认为这是更好的答案。跨度>
  • @AllanCameron 那是由于默认的rel.tol = .Machine$double.eps^0.25 (0.0001220703),试试我的rel.tol = eps (0.0000000149),积分是1。
  • @RuiBarradas ,我将使用您的答案,因为与第一个相比,它需要稍作修改!谢谢你们的宝贵帮助!
【解决方案2】:

如果你需要做一个双积分,你可以integrate两次:

bvtnorm <- function(y, mu_x = 10, mu_y = 5, sigma_x = 3, sigma_y = 7, rho = 0.4) {
    
    function(x) 
      1 / (2 * pi * sigma_x * sigma_y * sqrt(1 - rho ^ 2)) * 
      exp(- 1 / (2 * (1 - rho ^ 2)) * 
            (((x - mu_x) / sigma_x) ^ 2 + 
            ((y - mu_y) / sigma_y) ^ 2 - 2 * rho * (x - mu_x) * (y - mu_y) / 
            (sigma_x * sigma_y)))
  }
  
  f3 <- function(y)
  {
    f2 <- bvtnorm(y = y)
    integrate(f2, lower = -Inf, upper = Inf)$value
  }
  
  integrate(Vectorize(f3), -Inf, Inf)
#> 1.000027 with absolute error < 1.8e-05

正如预期的那样,这给出了一个非常接近 1 的答案。

reprex package (v0.3.0) 于 2020-09-05 创建

【讨论】:

  • 是的,这很有帮助!我已经尝试使用“rmutil”包,但是当边界等于 Inf 时它非常慢。相反,您的解决方案似乎对我有用。再次非常感谢!
猜你喜欢
  • 2019-10-08
  • 2012-02-13
  • 1970-01-01
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
相关资源
最近更新 更多