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

使用geom_density绘制的密度图为何未触达X轴?

问题:密度图曲线超出x=1范围的修复方案

我正在绘制国会代表配对投票一致率的概率密度图,对比同党派与跨党派配对的投票一致率分布。为每位国会议员创建配对,追踪所有唱名投票并计算每对的一致率(范围0-1,1代表全一致)。但部分国会的数据绘图时,右侧曲线未触达X轴,甚至超出x=1的范围。

原代码:

h117$pdplot <- 
  ggplot(data = 
         h117$pairs_votes_proportions %>%
         filter(proportion_of_agreements < 1 & proportion_of_agreements > 0.00), 
       aes(
         x = proportion_of_agreements,
         fill = pair_type)) +
  geom_density(adjust = 2, 
               alpha = 0.4, 
               size = 0.7) +
  scale_fill_grey(start = 0.1, end = 0.8) +
  labs(title = paste("House of Representatives 117;",length(unique(h117$votes$rollnumber)),"roll calls"),
       x = "Proportion of Agreements",
       y = "Density") +
  theme_minimal() +
   theme(legend.position = "none",
        plot.title = element_text(hjust = 0.5, face = "bold")) +
  xlim(0, 1)

问题原因

曲线超出x=1范围的核心原因是密度估计的平滑特性:geom_density默认采用高斯核做平滑拟合,当大量数据集中在接近1的区间时,算法会自然外推到x=1以外的区域。而xlim(0,1)只是生硬截断了显示范围,并没有调整密度计算的边界,导致曲线在截断处无法触达X轴。

修复方案

要彻底解决这个问题,需要同时限制密度计算的取值范围,并确保绘图边界贴合数据区间。修改后的代码如下:

h117$pdplot <- 
  ggplot(data = 
         h117$pairs_votes_proportions %>%
         filter(proportion_of_agreements < 1 & proportion_of_agreements > 0.00), 
       aes(
         x = proportion_of_agreements,
         fill = pair_type)) +
  # 用stat_density替代geom_density,强制截断外推部分
  stat_density(
    adjust = 2,
    alpha = 0.4,
    size = 0.7,
    trim = TRUE,  # 仅在数据存在的范围内计算密度
    geom = "density",
    # 双重保险:把x值强制限制在0-1区间内
    aes(x = pmax(pmin(proportion_of_agreements, 1), 0))
  ) +
  scale_fill_grey(start = 0.1, end = 0.8) +
  labs(title = paste("House of Representatives 117;",length(unique(h117$votes$rollnumber)),"roll calls"),
       x = "Proportion of Agreements",
       y = "Density") +
  theme_minimal() +
  theme(legend.position = "none",
        plot.title = element_text(hjust = 0.5, face = "bold")) +
  # 用scale_x_continuous替代xlim,让轴边界完全贴合0-1
  scale_x_continuous(limits = c(0, 1), expand = c(0, 0))

关键修改点

  • trim = TRUE:强制密度曲线只在实际数据覆盖的区间绘制,禁止算法外推到数据范围之外
  • pmax(pmin(proportion_of_agreements, 1), 0):确保所有x值被严格限制在0-1之间,避免极端值干扰拟合
  • scale_x_continuous(limits = c(0,1), expand = c(0,0)):替代xlim,让X轴的起始/结束位置完全对齐0和1,曲线能完整贴合X轴边界,不会被截断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:22:39