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

如何阻止geom_density_ridges显示数据中不存在的尾部数值?

解决geom_density_ridges()显示不存在的长尾部问题

哈哈,这个坑我踩过!你已经把负温数据删掉了,但geom_density_ridges()画出来的图还是出现了不存在的负温尾部,对吧?其实这是密度估计算法的锅——默认的高斯核平滑会自动延伸曲线,哪怕数据里根本没有边界外的值,尤其是当你的数据集中在某个区间的边缘(比如这里的0度下限),这种“脑补”出来的尾部就特别显眼。

下面给你几个实用的解决办法:

方法1:截断曲线到数据实际范围(最直接)

用scale_x_continuous()设置x轴的下限为0,同时用scales::squish把超出范围的部分压缩到边界,这样多余的尾部就会被切掉:

library(tidyverse)
library(ggridges)
data("lincoln_weather")

# 移除“最低气温[华氏度]”的所有负值
d <- lincoln_weather[lincoln_weather$`Min Temperature [F]`>=0,]

ggplot(d, aes(`Min Temperature [F]`, Month)) + 
  geom_density_ridges(rel_min_height=.01) +
  scale_x_continuous(limits = c(0, NA), oob = scales::squish)

方法2:调整密度估计的核函数或平滑程度

你可以换用更“保守”的核函数(比如矩形核),或者缩小平滑调整参数,让曲线更贴合实际数据分布:

ggplot(d, aes(`Min Temperature [F]`, Month)) + 
  geom_density_ridges(rel_min_height=.01, 
                      stat = "density",
                      kernel = "rectangular", # 换用矩形核
                      adjust = 0.8) # 减小平滑程度,数值越小越贴合数据

方法3:手动计算密度并过滤(最灵活)

如果需要更精细的控制,可以先自己计算每个月份的密度,只保留数据范围内的部分,再用stat="identity"绘图:

# 提前计算每个月份的密度,限定范围从0到该月最高温
d_density <- d %>%
  group_by(Month) %>%
  summarize(density = list(density(`Min Temperature [F]`, 
                                   from = 0, 
                                   to = max(`Min Temperature [F]`)))) %>%
  unnest_wider(density) %>%
  unnest(c(x, y))

# 使用预计算的密度绘图
ggplot(d_density, aes(x, Month, height = y)) +
  geom_density_ridges(stat = "identity", rel_min_height = .01)

其中方法1是最省心有效的,基本能解决大部分这类问题~

内容的提问来源于stack exchange,提问作者John J.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:47:02