ggplot添加geom_density后stat_function绘制的泊松曲线异常
问题:ggplot添加密度曲线后泊松分布曲线异常偏移
我正在使用Ecdat库中的PatentsRD数据集,遇到了ggplot的异常行为,无法解释。
我绘制了两条泊松分布曲线(一条使用公式计算,一条使用dpois函数),以验证它们是否完全一致:
library(tidyverse) library(Ecdat) data(PatentsRD) plot <- ggplot(data = data.frame(x = c(0:100)), aes(x = x))+ stat_function(fun = function(x){(mean(PatentsRD$patent)^x)/(factorial(x))*exp(-mean(PatentsRD$patent))}, color = "red")+ stat_function(fun = function(x){dpois(x, mean(PatentsRD$patent))}, color = "green") plot
此时两条曲线完全重合。但当我尝试添加数据集的密度函数后,情况出现异常:
plot + geom_density(data = PatentsRD, aes(x = patent))
添加后原本重合的红、绿曲线不再一致,且两者的高度也偏离了正确值(原本略高于0.05),请问这是什么原因导致的?
原因分析与解决方案
这是因为**geom_density()默认会对密度曲线做归一化处理**,要求曲线下的总面积为1,但你绘制的红、绿曲线是泊松分布的概率质量函数(PMF),属于离散分布的概率值,和连续分布的概率密度函数(PDF)逻辑完全不同。
具体差异:
- 泊松PMF是每个整数点上的事件发生概率,所有点的概率总和为1,单个点的高度就是该事件发生的概率。
geom_density生成的是连续密度曲线,它通过核估计把离散数据拟合为连续分布,并且强制曲线下面积为1,这会让y轴的刻度范围被PDF的数值拉伸或压缩,进而让原本重合的PMF曲线显示比例变形,看起来不再重合且高度异常。
解决方法:
方法1:锁定y轴范围,保留PMF的正确显示
先计算泊松PMF的最大取值,手动指定y轴范围,避免被密度曲线的y值影响:
mean_patent <- mean(PatentsRD$patent) plot <- ggplot(data = data.frame(x = c(0:100)), aes(x = x))+ stat_function(fun = function(x){(mean_patent^x)/(factorial(x))*exp(-mean_patent)}, color = "red")+ stat_function(fun = function(x){dpois(x, mean_patent)}, color = "green")+ geom_density(data = PatentsRD, aes(x = patent), alpha = 0.3) + ylim(0, max(dpois(0:100, mean_patent)) * 1.1) # 预留10%空间避免曲线被截断 plot
方法2:用直方图匹配PMF的逻辑
把离散数据的分布转换为频率密度,和泊松PMF的量级对齐:
mean_patent <- mean(PatentsRD$patent) ggplot() + stat_function(data = data.frame(x = c(0:100)), aes(x = x), fun = function(x){dpois(x, mean_patent)}, color = "green", size = 1) + geom_histogram(data = PatentsRD, aes(x = patent, y = ..density..), binwidth = 1, fill = "blue", alpha = 0.3)
内容的提问来源于stack exchange,提问作者Sebastian Geis
相关产品推荐
相关产品推荐

