调整ggplot折线图Y轴,可视化差异悬殊的age_group计数
解决分组计数差异过大的折线图展示问题
现有一个包含age_group(取值1-5)的data.table,共801,921条观测值。需要用ggplot绘制折线图,以age_group为X轴,各分组的总计数为Y轴。其中age_group1的观测值达274,000条,而age_group5仅7条。当前设置Y轴范围0-280000时,3、4、5组几乎无法被观察到。已考虑拆分1、2组单独展示,或是将Y轴适配3、4、5组的范围(0-350),在图上方标记1、2组的计数点并用虚线连接至折线图,现寻求其他可行解决方案。
现有代码:
ggplot(data = df1[type == "WORK"], aes(x = age_group)) + geom_line(stat = "bin", binwidth = 0.5, color = "lightblue") + labs(x = "age", y = "count") + scale_x_continuous(breaks = 1:5) + scale_y_continuous(limits = c(0, 274150), breaks = seq(0, 274150, by = 50000)) + theme_minimal()
可行解决方案
1. 对数转换Y轴
通过对数转换压缩大数值的范围,同时保留小分组的差异,搭配实际计数标签让读者明确数值。
代码示例:
ggplot(data = df1[type == "WORK"], aes(x = age_group)) + geom_line(stat = "bin", binwidth = 0.5, color = "lightblue") + geom_text(stat = "bin", binwidth = 0.5, aes(label = ..count..), vjust = -0.5) + labs(x = "age", y = "count (log10 scale)") + scale_x_continuous(breaks = 1:5) + scale_y_log10(breaks = c(10, 100, 1000, 10000, 100000, 274000)) + annotation_logticks(sides = "l") + theme_minimal()
2. 双Y轴展示
左侧Y轴对应1、2组的大计数,右侧Y轴对应3、4、5组的小计数,用不同颜色区分折线,避免混淆。
代码示例:
# 预计算各分组计数 count_df <- df1[type == "WORK"][, .N, by = age_group] ggplot(count_df) + geom_line(aes(x = age_group, y = N, color = "Group 1-2"), size = 1) + geom_line(aes(x = age_group, y = N * (274150 / 350), color = "Group 3-5"), size = 1) + geom_text(aes(x = age_group, y = N, label = N), vjust = -0.5, color = "darkblue") + geom_text(aes(x = age_group, y = N * (274150 / 350), label = N), vjust = 1.5, color = "darkred") + labs(x = "age", y = "Count (Group 1-2)", color = "Group") + scale_x_continuous(breaks = 1:5) + scale_y_continuous( limits = c(0, 274150), breaks = seq(0, 274150, by = 50000), sec.axis = sec_axis(~ . / (274150 / 350), name = "Count (Group 3-5)", breaks = seq(0, 350, by = 50)) ) + scale_color_manual(values = c("Group 1-2" = "lightblue", "Group 3-5" = "salmon")) + theme_minimal()
3. 分面拆分展示
将1、2组和3、4、5组拆分为两个子图,用分面布局保留各自的细节,同时能整体对比。
代码示例:
# 给分组添加规模标签 count_df <- df1[type == "WORK"][, .N, by = age_group][, size_group := ifelse(age_group %in% 1:2, "Large Groups", "Small Groups")] ggplot(count_df, aes(x = age_group, y = N)) + geom_line(stat = "identity", color = "lightblue") + geom_text(aes(label = N), vjust = -0.5) + labs(x = "age", y = "count") + scale_x_continuous(breaks = 1:5) + facet_wrap(~size_group, scales = "free_y") + theme_minimal()
4. 主图+局部放大inset
保持原Y轴范围,用加粗、异色折线突出小分组,同时在图内嵌入小分组的放大子图,兼顾整体和细节。
代码示例:
library(grid) # 主图 p_main <- ggplot(data = df1[type == "WORK"], aes(x = age_group)) + geom_line(stat = "bin", binwidth = 0.5, color = "lightblue") + geom_line(data = df1[type == "WORK" & age_group %in% 3:5], stat = "bin", binwidth = 0.5, color = "red", size = 1.2) + geom_text(stat = "bin", binwidth = 0.5, aes(label = ..count..), vjust = -0.5) + labs(x = "age", y = "count") + scale_x_continuous(breaks = 1:5) + scale_y_continuous(limits = c(0, 274150), breaks = seq(0, 274150, by = 50000)) + theme_minimal() + theme(plot.margin = unit(c(1, 1, 1, 1), "cm")) # 小分组放大图 p_inset <- ggplot(data = df1[type == "WORK" & age_group %in% 3:5], aes(x = age_group)) + geom_line(stat = "bin", binwidth = 0.5, color = "red") + geom_text(stat = "bin", binwidth = 0.5, aes(label = ..count..), vjust = -0.5) + labs(x = "", y = "") + scale_x_continuous(breaks = 3:5) + scale_y_continuous(limits = c(0, 350)) + theme_minimal() + theme(axis.text = element_text(size = 8), plot.background = element_rect(fill = "white", color = "black")) # 组合展示 vp <- viewport(width = 0.3, height = 0.3, x = 0.75, y = 0.25) print(p_main) print(p_inset, vp = vp)
内容的提问来源于stack exchange,提问作者Ann
相关产品推荐
相关产品推荐

