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

ggplot2如何将分组直方图改为分箱计数的点图或折线图

问题说明

现有记录不同组件辐射时长与故障情况的数据集,样例结构如下:

> head(df10)
  Gen_X_ray_h Component
1           0   Housing
2           0   Housing
3           0   Housing
4           0   Housing
5           0   Housing
6           0   Housing

此前使用堆叠直方图展示故障分布,但堆叠形式无法清晰观察不同组件故障数随辐射时长的升降趋势;直接将geom_histogram()替换为geom_point()时会强制要求指定y轴映射。需要保留原有分箱统计逻辑(支持自定义binwidth分箱宽度),实现多分组下故障计数与辐射时长对应关系的点图/折线图。
原有绘图代码如下:

ggplot(alpha = 0.75) + 
  geom_histogram(df10, mapping = aes(x = Gen_X_ray_h, fill = Component)
                 , binwidth = 500
                 , color = "black"
                 ) +
  labs(title = "Failures") +
  xlab("radiation hours / h") +
  guides(fill=guide_legend("")) +
  scale_x_continuous(n.breaks = 28) + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) 

补充样例数据结构:

dput(df10[1:60,])
structure(list(Gen_X_ray_h = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3.5, 3.5, 
5, 5, 6.19999999999999, 10, 12.2, 14, 24, 24, 24), Component = c("Housing", 
"Housing", "Housing", "Housing", "Housing", "Housing", "Housing", 
"Housing", "Housing", "Housing", "Housing", "Housing", "Housing", 
"HV_Board", "HV_Board", "HV_Board", "HV_Diode", "HV_Diode", "HV_Diode", 
"HV_Diode", "HV_Diode", "HV_Diode", "HV_Diode", "HV_Diode", "HV_Diode", 
"HV_Resistor", "HV_Resistor", "HV_Resistor", "HV_Resistor", "HV_Transformer", 
"HV_Transformer", "HV_Transformer", "Tube", "Tube", "Tube", "Tube", 
"Tube", "Tube", "Tube", "Tube", "Tube", "Tube_crack", "Tube_crack", 
"Tube_crack", "Tube_crack", "Tube_crack", "Tube_crack", "Tube_crack", 
"Housing", "HV_Board", "Tube", "Housing", "HV_Transformer", "HV_Diode", 
"HV_Diode", "HV_Resistor", "HV_capac", "Housing", "Tube", "Tube_crack"
)), row.names = c(NA, 60L), class = "data.frame")
实现方案

核心逻辑是复用直方图的分箱统计规则,将统计得到的分箱计数作为y轴映射给点/线图层,不需要改动原有分箱口径,支持自由调整binwidth。

方案1:直接调用ggplot内置统计变换(无需提前处理数据)

geom_point()、geom_line()支持直接调用和直方图完全一致的bin统计变换,通过after_stat(count)直接调用内部计算的分箱故障数作为y轴,不需要额外写数据处理代码,统计结果和原直方图完全对齐:

ggplot(df10, 
       mapping = aes(x = Gen_X_ray_h, 
                     y = after_stat(count), 
                     color = Component, 
                     group = Component),
       alpha = 0.75) + 
  # 点图层
  geom_point(stat = "bin", binwidth = 500, size = 2) +
  # 需要折线就保留下面这行,不需要可直接删除
  geom_line(stat = "bin", binwidth = 500, linewidth = 1) +
  labs(title = "Failures", y = "故障计数") +
  xlab("radiation hours / h") +
  guides(color = guide_legend("")) +
  scale_x_continuous(n.breaks = 28) + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

提示:如果需要点带填充色,可以将点图层替换为geom_point(stat = "bin", binwidth = 500, size = 2, shape = 21),同时在aes中将color替换为fill即可,和原直方图的填充逻辑保持一致。如果组件数量较多,追加facet_wrap(~Component, scales = "free_y")分面展示,趋势会更清晰。

方案2:手动分箱统计(适合需要自定义调整统计结果的场景)

如果后续需要对分箱后的计数做二次计算,可以先手动完成分箱计数再绘图,分箱规则可以和直方图完全对齐:

library(dplyr)
# 自定义分箱宽度
binwidth <- 500
df_binned <- df10 %>%
  mutate(
    # 按设定宽度分箱,取每个箱的左端点作为x轴坐标,和geom_histogram默认规则一致
    bin = floor(Gen_X_ray_h / binwidth) * binwidth
  ) %>%
  count(bin, Component, name = "count")

# 用预处理好的分箱数据绘图
ggplot(df_binned,
       mapping = aes(x = bin, 
                     y = count, 
                     color = Component, 
                     group = Component),
       alpha = 0.75) +
  geom_point(size = 2) +
  geom_line(linewidth = 1) +
  labs(title = "Failures", y = "故障计数") +
  xlab("radiation hours / h") +
  guides(color = guide_legend("")) +
  scale_x_continuous(n.breaks = 28) + 
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 09:45:18