如何在R的ggplot中创建双轴(柱状+折线)图表?
在ggplot中实现柱状图+折线图的双轴图表
问题
我需要在R的ggplot中创建类似Excel的双轴图表,包含柱状图和折线图,两个Y轴的刻度范围不同。我已经分别写出了柱状图和折线图的代码,但尝试多种方法都无法将二者合并,请求帮助实现整合。
原柱状图代码:
inf_conc <- ggplot(data=data, aes(x=Day, y=inf)) + geom_bar(stat="identity", width=0.4, color="red3", fill="red3") + ggtitle("Influent Microplastic Concentration and Flow Rate") + xlab("Day") + ylab("Microplastic Concentration (MPs/L)") + scale_y_continuous(limits =c(0, 50), breaks = seq(0, 50, 5)) inf_conc + theme(axis.text = element_text(size = 20, colour = "black"), plot.title = element_text(size =25, hjust = 0.5, face = "bold"), axis.title = element_text(size = 20, face = "bold", margin = 5))
原折线图代码:
inf_flow <- ggplot(data=data, aes(x=Day, y=flow, group = 1)) + geom_line(stat = "identity", colour ="blue4") + geom_point(colour ="blue4") + ylab("Inlet flow L/s")+ xlab("Day")+ scale_y_continuous(limits=c(0,800), breaks = seq(0, 800, 100)) inf_flow + theme(axis.text = element_text(size = 20, colour = "black"), plot.title = element_text (size =25, hjust = 0.5, face = "bold"), axis.title = element_text(size = 20, face = "bold", margin = 5))
解决方案
ggplot原生支持通过sec_axis()创建次坐标轴,核心是将折线图的Y轴数据映射到柱状图的Y轴范围,再通过刻度转换还原真实值。以下是整合后的完整代码:
library(ggplot2) # 计算转换比例:将flow的0-800范围映射到inf的0-50范围 scale_factor <- 50 / 800 combined_plot <- ggplot(data = data, aes(x = Day)) + # 柱状图(主Y轴:左侧) geom_bar(aes(y = inf), stat = "identity", width = 0.4, color = "red3", fill = "red3") + # 折线图(数据先按比例缩放到主Y轴范围) geom_line(aes(y = flow * scale_factor), colour = "blue4", group = 1) + geom_point(aes(y = flow * scale_factor), colour = "blue4") + # 设置主、次Y轴 scale_y_continuous( name = "Microplastic Concentration (MPs/L)", limits = c(0, 50), breaks = seq(0, 50, 5), # 次Y轴(右侧):还原flow的真实刻度 sec.axis = sec_axis( trans = ~ . / scale_factor, name = "Inlet flow L/s", limits = c(0, 800), breaks = seq(0, 800, 100) ) ) + # 标题与轴标签 ggtitle("Influent Microplastic Concentration and Flow Rate") + xlab("Day") + # 统一主题样式 theme( axis.text = element_text(size = 20, colour = "black"), plot.title = element_text(size = 25, hjust = 0.5, face = "bold"), axis.title = element_text(size = 20, face = "bold", margin = margin(0, 20, 0, 0)), # 次Y轴文字与折线同色 axis.title.y.right = element_text(color = "blue4"), axis.text.y.right = element_text(color = "blue4"), # 主Y轴文字与柱状图同色 axis.title.y.left = element_text(color = "red3"), axis.text.y.left = element_text(color = "red3") ) print(combined_plot)
关键细节
- 数据缩放:折线图的
flow数据必须乘以scale_factor,将其数值范围压缩到柱状图的Y轴区间内,否则无法在同一坐标系中显示。 - 刻度还原:
sec_axis()的trans参数使用反向公式,将缩放后的值还原为flow的真实刻度,确保次Y轴显示正确数值。 - 视觉区分:通过颜色匹配坐标轴与对应图表元素,让读者更容易区分两组数据。
- 主题优化:合并原代码中重复的
theme设置,避免冗余,同时调整边距让布局更美观。
内容的提问来源于stack exchange,提问作者D.dot
相关产品推荐
相关产品推荐

