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

R ggplot使用dlnorm为工资密度直方图叠加对数正态曲线的参数问题

问题描述

我使用加拿大人口普查数据绘制x轴为工资(Wages)、y轴为密度的直方图,想要叠加对数正态分布的dlnorm曲线,但不确定meanlog和sdlog参数的正确取值。我先后尝试直接传入mean(data$Wages)、sd(data$Wages)以及两者的自然对数值作为参数,生成的曲线都和现有密度直方图分布差异极大。请问是否是我的数据不符合对数正态分布?如何获取正确的meanlog和sdlog参数?
我的代码如下:

inc_plot <- data_adults %>%
  ggplot(aes(x=Wages)) +
  geom_histogram(aes(y=..density..),  bins=100,fill="transparent", colour="black")+
  scale_x_continuous(labels=scales::comma) +
  stat_function(fun = dlnorm,
      args = list(meanlog = 48637.91, sdlog = 62459.15),
      col = "red")

inc_plot

当前代码中使用的参数就是前述的工资均值和标准差,生成的效果如下图:
效果图


解决方案

核心错误原因

你对dlnorm的参数定义理解有误:

  • meanlog对应的是原始工资数据取自然对数后的均值,不是原始工资的均值,也不是原始均值的对数值
  • sdlog对应的是原始工资数据取自然对数后的标准差,不是原始工资的标准差,也不是原始标准差的对数值
    你直接传入原始工资的均值、标准差,参数量级完全不符合要求,自然曲线和直方图匹配不上。

正确操作步骤

  1. 清洗无效数据:对数正态分布仅支持正值,先删除Wages列中小于等于0的观测,避免取对数时报错
  2. 计算参数:对清洗后的Wages列取自然对数,再计算该对数序列的均值和标准差,即为meanlog和sdlog的正确取值

修正后代码

# 清洗数据+计算参数
data_adults_clean <- data_adults %>%
  filter(Wages > 0)
wages_log <- log(data_adults_clean$Wages)
meanlog_val <- mean(wages_log)
sdlog_val <- sd(wages_log)

# 绘图
inc_plot <- data_adults_clean %>%
  ggplot(aes(x=Wages)) +
  geom_histogram(aes(y=..density..),  bins=100,fill="transparent", colour="black")+
  scale_x_continuous(labels=scales::comma) +
  stat_function(fun = dlnorm,
      args = list(meanlog = meanlog_val, sdlog = sdlog_val),
      col = "red")

inc_plot

分布符合性验证

如果按上述方法调整后,曲线和直方图仍然差异较大,说明你的工资数据确实不符合对数正态分布,可通过两种方法验证:

  • 绘制对数工资的Q-Q图:若散点基本沿着正态分布对角线分布,说明符合对数正态,反之不符合
  • 对对数工资做Shapiro-Wilk正态检验,p值大于显著性水平(通常为0.05)则认为符合对数正态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:09:00