如何阻止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.
相关产品推荐
相关产品推荐

