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

在ggplot2中添加基于相对频率的透明直方图轮廓

在ggplot2中绘制无内部竖线的相对频率直方图轮廓

问题背景

需要对比两个分布:一个用填充直方图展示,另一个用无内部竖线的直方图轮廓展示,且均为相对频率直方图(y轴使用density * width)。尝试多种方法均存在问题:

  • geom_histogram(fill=NA)会生成内部竖线,干扰可读性
  • geom_freqpoly生成锯齿状线条,不符合平条形轮廓的需求
  • stat_bin(geom="step")端点不与y=0连接,且两端不对齐x=0/x=1边界
  • geom_density过度平滑丢失分布细节,边界不对齐,且密度与相对频率的匹配逻辑不清晰

解决方案

方法1:叠加直方图(简单高效)

通过叠加两层geom_histogram实现:先绘制白色填充的直方图(覆盖内部竖线),再绘制仅带黑色边框的直方图,保留外层轮廓。

library(ggplot2)
library(ggpubr)

set.seed(22)
# 创建模拟数据
flavor <- data.frame(
  color = sample(c('red', 'blue', 'green'), 1500, TRUE),
  flavor = sample.int(n = 100, size = 1500, replace = TRUE) / 100
)

flavor2 <- 
  data.frame(
    color = sample(c('red', 'blue', 'green'), 1500, TRUE),
    flavor = (sample.int(n = 100, size = 1500, replace = TRUE) / 100) ^ 2
  )

# 绘图代码
ggplot() +
  # 第一个分布:填充直方图
  geom_histogram(data = flavor,
                 aes(x = flavor, y = after_stat(density * width)),
                 bins = 34, alpha = 0.5, fill = "#619CFF") +
  # 先绘制白色填充的直方图,覆盖内部竖线
  geom_histogram(data = flavor2,
                 aes(x = flavor, y = after_stat(density * width)),
                 bins = 34, fill = "white", color = NA) +
  # 再绘制仅带边框的直方图,保留轮廓
  geom_histogram(data = flavor2,
                 aes(x = flavor, y = after_stat(density * width)),
                 bins = 34, fill = NA, color = "black", size = 0.7) +
  facet_wrap(~color) +
  labs(y = "相对频率", x = "Flavor Value") +
  theme_bw()

方法2:手动绘制轮廓(更灵活)

先提取分箱统计数据,再用geom_polygon绘制完整的直方图轮廓,确保边界对齐x=0/x=1,且端点与y=0连接。

library(ggplot2)
library(dplyr)

# 复用上面的模拟数据...

# 定义函数提取分箱统计数据
get_bin_stats <- function(data, var, bins = 34) {
  data %>%
    group_by(color) %>%
    group_map(function(.df, .grp) {
      # 用stat_bin计算分箱数据
      p <- ggplot(.df, aes(x = {{var}})) +
        stat_bin(bins = bins, aes(y = after_stat(density * width)), geom = "blank")
      layer_data(p) %>%
        mutate(color = .grp$color) %>%
        select(xmin, xmax, y, color)
    }) %>%
    bind_rows()
}

# 获取flavor2的分箱数据
flavor2_bins <- get_bin_stats(flavor2, flavor, bins = 34)

# 绘图
ggplot() +
  # 填充直方图
  geom_histogram(data = flavor,
                 aes(x = flavor, y = after_stat(density * width)),
                 bins = 34, alpha = 0.5, fill = "#619CFF") +
  # 用geom_polygon绘制轮廓:连接分箱左右端点+底部0点
  geom_polygon(data = flavor2_bins,
               aes(x = c(xmin, rev(xmax)), y = c(y, rep(0, n()))),
               color = "black", fill = NA, group = color) +
  facet_wrap(~color) +
  labs(y = "相对频率", x = "Flavor Value") +
  theme_bw()

效果说明

两种方法都能生成无内部竖线的直方图轮廓,且保持相对频率的正确性:

  • 方法1操作简单,无需额外数据处理,适合快速绘图
  • 方法2更灵活,可自定义轮廓的连接方式,适合需要调整细节的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:53:17