如何在R直方图中添加基于tonne.km权重的累积趋势线并调整双轴?
解决方案:带加权累积趋势线的直方图调整
不需要更换图表类型,通过正确使用weight参数和ggplot的统计变量,就能实现主轴显示区间tonne.km总和、次轴显示加权累积占比的需求。
直接在ggplot中实现(推荐)
利用ggplot的内部统计变量..sum..(对应weight参数的区间总和),直接生成直方图和累积曲线:
library(tidyverse) library(scales) # 测试数据 distance <- rnorm(1000000, mean = 1000, sd = 500) tonne.km <- rnorm(1000000, mean = 25000, sd = 500) dist.tk.test <- tibble(distance, tonne.km) # 修正后的绘图代码 dist.tk.test %>% ggplot() + # 直方图:每个柱子高度为对应区间的tonne.km总和 geom_histogram( aes(x = distance, y = ..sum.., weight = tonne.km), bins = 50, fill = "lightblue", alpha = 0.7 ) + # 累积趋势线:基于tonne.km的加权累积占比 stat_bin( aes(x = distance, y = cumsum(..sum..) / sum(..sum..), group = 1), geom = "line", color = "red", size = 1, weight = tonne.km ) + # x轴格式化 scale_x_continuous(label = comma, breaks = extended_breaks(10)) + # 双y轴设置 scale_y_continuous( name = "Tonne.km 总和", labels = comma, sec.axis = sec_axis(~ ., labels = percent, name = "累积占比 (%)") ) + theme_minimal()
关键调整点
- 直方图:将
y=..density..替换为y=..sum..,结合weight=tonne.km,直接输出区间内tonne.km的总和,而非归一化的密度值。 - 累积曲线:
- 必须添加
weight=tonne.km,确保累积计算基于tonne.km的权重,而非样本数量。 - 用
cumsum(..sum..) / sum(..sum..)将累积总和转换为占比,匹配右侧次轴的百分比格式。 - 添加
group=1,避免ggplot因分组逻辑中断线条绘制。
- 必须添加
预处理数据实现(更透明)
如果需要更直观地控制数据分组和计算逻辑,可以提前预处理数据,再绘制图表:
# 计算总tonne.km,用于后续占比转换 total_tk <- sum(dist.tk.test$tonne.km) # 分组计算每个distance区间的tonne.km总和与累积占比 dist_binned <- dist.tk.test %>% mutate(distance_bin = cut(distance, breaks = 50)) %>% group_by(distance_bin) %>% summarise(tk_sum = sum(tonne.km)) %>% mutate( # 取区间中点作为x轴绘制位置 distance_mid = map_dbl(distance_bin, ~mean(as.numeric(.)[1:2])), # 计算累积占比 cumulative_pct = cumsum(tk_sum) / total_tk ) # 绘图 ggplot(dist_binned) + geom_col(aes(x = distance_mid, y = tk_sum), fill = "lightblue", alpha = 0.7) + # 将累积占比转换为主轴同单位,再通过次轴转换回百分比 geom_line(aes(x = distance_mid, y = cumulative_pct * total_tk), color = "red", size = 1) + scale_x_continuous(label = comma, breaks = extended_breaks(10)) + scale_y_continuous( name = "Tonne.km 总和", labels = comma, sec.axis = sec_axis(~ . / total_tk, labels = percent, name = "累积占比 (%)") ) + theme_minimal()
预处理优势
可以直接查看每个区间的具体数值,方便后续分析;同时灵活控制bin的划分规则(比如自定义断点)。
内容的提问来源于stack exchange,提问作者David Færgeman
相关产品推荐
相关产品推荐

