基本R函数卷积

时间:2017-04-28 16:31:32

标签: r convolution probability-density

我正在构建一组函数,它们从两个独立随机变量的pdf中返回概率密度函数(pdfs)。

最常见的例子是独立随机变量 X Y 的总和,它们是由pdfs的卷积给出的。

post之后,我定义了以下函数,该函数将一对pdfs作为参数,并返回它们的卷积:

dSumXY <- function(dX, dY){

  # Create convolution of distributions.
  dReturn <- function(z){
    integrate( function(x,z){
      dX(x) * dY(z - x) },
      -Inf, Inf, z)$value
  }

  # Vectorize convolution.
  dReturn <- Vectorize(dReturn)

  return(dReturn)  
}

这在以下示例中按预期工作:

# Define pdfs of two (identical) uniform [-1,1] distributions
unifX <- function(x) dunif(x, min = -1, max = 1)
unifY <- function(x) dunif(x, min = -1, max = 1)

# Find convolution of their pdfs.
convXY <- dSumXY(unifX, unifY)

# Plot the convolved pdf.
plot(seq(-3,3,by = 0.1), convXY(seq(-3,3,by = 0.1) ), type = 'l')

# Sample from the distribution
convSample <- runif(10000, min = -1, max = 1) + runif(10000, min = -1, max = 1)

# Plot density of sample.
lines( density(convSample) , col = "red" )

更一般地说,这适用于多对均匀分布的组合,但是当我尝试卷积一对均匀[1,2]分布时,我得不到真正的结果:

# Define pdfs of two (identical) uniform [1,2] distributions
unifX2 <- function(x) dunif(x, min = 1, max = 2)
unifY2 <- function(x) dunif(x, min = 1, max = 2)

# Find convolution of their pdfs.
convXY2 <- dSumXY(unifX2, unifY2)

# Plot the convolved pdf.
plot(seq(1,5,by = 0.1), convXY2(seq(1,5,by = 0.1) ), type = 'l')

# Sample from the distribution
convSample2 <- runif(10000, min = 1, max = 2) + runif(10000, min = 1, max = 2)

# Plot density of sample.
lines( density(convSample2) , col = "red" )

特别是(有一点概率知识!)很明显,两个Uniform [1,2]变量之和的pdf在3.75时应该是非零的;特别是它应该等于1/4。然而

# This should be equal to 1/4, but returns 0.
convXY2(3.75)

我在两台不同的机器上尝试了这个并重复了同样的问题,所以我很想知道问题出在哪里。

提前致谢。

2 个答案:

答案 0 :(得分:2)

问题来自Integrate函数,该函数正在努力解决该函数具有紧凑支持的问题,然而,它被要求在无限范围内进行集成。如果将积分范围更改为函数支持的范围(即[1,2]),那么它的工作没有问题。

答案 1 :(得分:0)

dunif处理整数...

dunif(.9, 1, 2)
[1] 0

dunif(1, 1, 2)
[1] 1

dunif(1.5, 1, 2)
[1] 1

dunif(2, 1, 2)
[1] 1

dunif(2.1, 1, 2)
[1] 0

如果你只使用函数的整数然后插值,你会得到预期的答案。

convXY2(2)
[1] 0

convXY2(3)
[1] 1

convXY2(4)
[1] 0

z <- 3.75
remainder <- z %% 1
convXY2(floor(z))*(1-remainder) + convXY2(ceiling(z))*(remainder) 
[1] 0.25

您的函数可以正常用于其他连续分发,因此您可能只需要在包装函数中考虑这种特定情况。那或者使用除了dunif之外的东西,它可以根据你提供的精度有效地划分你的概率。

dunif2 <- function(x, min, max) { if (x >= min & x <= max) { return(10^-nchar(strsplit(as.character(x), "\\.")[[1]][[2]])) } else { return(0) } }

dunif2(1.45, 1, 2)
[1] 0.01

dunif2(1.4, 1, 2)
[1] 0.1