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
相关产品推荐
相关产品推荐

