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

ggplot绘制密度图时曲线起始早于实际数据问题求助

问题原因与解决思路

原因

这是geom_density()默认的核密度估计行为导致的:核函数会对数据范围外的区域进行平滑拟合延伸,哪怕该区域没有实际数据点,因此药物B的密度曲线会超出它的最早处方日期(2012-01-31),出现在更早的时间区间。

解决思路

1. 截断密度曲线到数据实际范围

使用stat_density()替代geom_density(),并设置trim = TRUE,这样曲线会被严格截断在每种药物的实际日期范围两端,不会延伸到无数据区域:

drugs %>% 
    ggplot(aes(x=date, fill=drug_name, colour=drug_name)) +
    stat_density(alpha=0.5, geom="area", trim=TRUE) +
    theme_minimal()+
    scale_x_date(date_breaks = "1 year", 
                 date_labels = "%Y")+
    labs(x = "Years", y = "Density")

2. 限制x轴显示范围

直接通过scale_x_date()的limits参数设定x轴的最小/最大值,或者过滤数据只保留每种药物自身的有效日期区间:

# 方法A:设置x轴范围
drugs %>% 
    ggplot(aes(x=date, fill=drug_name, colour=drug_name)) +
    geom_density(alpha=0.5)+
    theme_minimal()+
    scale_x_date(date_breaks = "1 year", 
                 date_labels = "%Y",
                 limits = as.Date(c("2003-11-04", NA))) + # 保留药物A的起始日期,右侧不限制
    labs(x = "Years", y = "Density")

# 方法B:过滤数据,仅保留每种药物自身的有效日期
drugs %>%
    group_by(drug_name) %>%
    filter(date >= min(date)) %>%
    ungroup() %>%
    ggplot(aes(x=date, fill=drug_name, colour=drug_name)) +
    geom_density(alpha=0.5)+
    theme_minimal()+
    scale_x_date(date_breaks = "1 year", 
                 date_labels = "%Y")+
    labs(x = "Years", y = "Density")

3. 调整核密度带宽

减小带宽参数bw,让密度曲线更贴近实际数据点,减少向外延伸的程度。带宽可以指定具体天数(如bw=30代表30天),或用adjust参数按比例调整默认带宽:

drugs %>% 
    ggplot(aes(x=date, fill=drug_name, colour=drug_name)) +
    geom_density(alpha=0.5, bw = 30) + # 可根据数据分布调整bw数值
    theme_minimal()+
    scale_x_date(date_breaks = "1 year", 
                 date_labels = "%Y")+
    labs(x = "Years", y = "Density")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:00:18