You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取R中两个分布卷积结果对应的x值?

如何获取两个分布卷积后的对应x值?

我知道这个问题可能更偏向统计理论,但我的核心需求是在R语言里实现对应的计算。最近我在尝试把多个分布相加,查看结果的分布情况,这里就用两个正态分布随机变量p1和p2来举例:

set.seed(21)
N <- 1000
p1 <- rnorm(N, mean = 0, sd = 1)
p2 <- rnorm(N, mean = 10, sd = 1)

我已经能画出它们的分布图像:

library(tidyverse)
data.frame(p1, p2) %>% gather(key="dist", value="value") %>% ggplot(aes(value, color=dist)) + geom_density()

之后我想用convolve函数实现分布相加,但卡在了如何为卷积后的结果分布匹配准确的x值上。之前手动添加的方式太不准确了,我试过类似这样的代码得到卷积结果并绘图,但x轴的对应关系一直不对:

pdf.c <- convolve(pdf1.y, pdf2.y, type = "open")
plot(pdf.c, type="l")

我感觉自己在统计基础上有认知缺口,想搞明白怎么正确获取新分布对应的x值。

附一下我生成pdf1和pdf2的代码:

set.seed(21)
N <- 1000
p1 <- rnorm(N, mean = 0, sd = 1)
p2 <- rnorm(N, mean = 10, sd = 1)
pdf1.x <- density(p1)$x
pdf2.x <- density(p2)$x
pdf1.y <- density(p1)$y / sum(density(p1)$y)
pdf2.y <- density(p2)$y / sum(density(p2)$y)
df1 <- data.frame(pdf.x = pdf1.x, pdf.y = pdf1.y, dist = "1", stringsAsFactors = FALSE)
df2 <- data.frame(pdf.x = pdf2.x, pdf.y = pdf2.y, dist = "2", stringsAsFactors = FALSE)
df <- bind_rows(df1, df2)

解决方案

其实核心是理解卷积的x值是两个原分布x值的所有可能和,但因为我们用的是密度估计后的离散点,需要先保证两个分布的x轴间隔一致,这样计算出来的卷积x轴才能准确对应。

步骤1:统一两个分布的x轴范围和间隔

首先,我们需要让pdf1.x和pdf2.x有相同的步长(间隔),并且覆盖足够大的范围,这样卷积后的结果不会丢失信息。可以用seq()来生成统一的x序列,然后用approx()把原密度值插值到这个统一的x轴上:

library(tidyverse)

# 先确定统一的x轴范围:取两个分布x的最小值到最大值的扩展范围
min_x <- min(pdf1.x, pdf2.x)
max_x <- max(pdf1.x, pdf2.x)
# 扩展一点范围,避免卷积后边缘截断
extended_min <- min_x - 3
extended_max <- max_x + 3
# 统一步长,用原密度的平均步长
step <- mean(diff(pdf1.x))
# 生成统一的x序列
unified_x <- seq(extended_min, extended_max, by = step)

# 把pdf1和pdf2的y值插值到统一x轴上
pdf1_y_unified <- approx(pdf1.x, pdf1.y, xout = unified_x)$y
pdf2_y_unified <- approx(pdf2.x, pdf2.y, xout = unified_x)$y
# 替换插值后的NA为0(边缘可能出现)
pdf1_y_unified[is.na(pdf1_y_unified)] <- 0
pdf2_y_unified[is.na(pdf2_y_unified)] <- 0

步骤2:计算卷积并生成对应的x值

当两个分布的x轴统一后,卷积的x值范围就是min(unified_x) + min(unified_x)到max(unified_x) + max(unified_x),步长和原统一x轴一致。用convolve计算后,对应的x序列可以这样生成:

# 计算卷积(注意convolve的type参数,这里用"open"对应线性卷积)
pdf_conv <- convolve(pdf1_y_unified, pdf2_y_unified, type = "open")
# 生成卷积对应的x值
conv_x <- seq(2*extended_min, 2*extended_max, by = step)
# 注意:convolve返回的长度是length(pdf1_y_unified) + length(pdf2_y_unified) - 1,和conv_x的长度一致

步骤3:绘图验证

现在就可以把原分布和卷积后的分布画在一起验证了:

# 整理数据
conv_df <- data.frame(x = conv_x, y = pdf_conv, dist = "p1+p2")
original_df <- bind_rows(
  data.frame(x = unified_x, y = pdf1_y_unified, dist = "p1"),
  data.frame(x = unified_x, y = pdf2_y_unified, dist = "p2")
)

# 绘图
ggplot() +
  geom_line(data = original_df, aes(x = x, y = y, color = dist)) +
  geom_line(data = conv_df, aes(x = x, y = y, color = dist), linetype = "dashed") +
  theme_minimal()

额外小技巧:利用正态分布性质简化计算

如果你是处理已知参数的正态分布,其实可以直接利用正态分布的性质:两个独立正态分布之和仍然是正态分布,均值是两者均值之和,方差是两者方差之和,这样可以直接生成理论分布来验证,比如:

# 理论分布的x和y
theory_x <- seq(8, 12, by = 0.1)
theory_y <- dnorm(theory_x, mean = 0+10, sd = sqrt(1+1))

内容的提问来源于stack exchange,提问作者Lloyd Christmas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:35:22