如何在R中使用ggplot2创建双X轴周销售对比图表?
在ggplot2中实现双X轴销售额对比图表
核心思路
ggplot2不支持直接绑定两个独立X变量,需以其中一个轴(如Semana_TW)为基础,通过轴转换/手动标签映射生成第二个轴(Semana_LY),同时确保两组数据的X轴位置严格对齐。
步骤1:整理数据
确保数据包含以下字段:
Semana_TW:本年周数Ventas_TW:本年对应周销售额(前3周为0)Semana_LY:上年偏移3周的对应周数Ventas_LY:上年对应周销售额
模拟你的场景构造示例数据:
sales_data <- data.frame( Semana_TW = 30:36, Ventas_TW = c(0, 0, 0, 1200, 1500, 1400, 1600), Semana_LY = 27:33, Ventas_LY = c(1100, 1300, 1250, 1220, 1480, 1350, 1550) )
步骤2:绘制双X轴图表
线性对应场景(LY比TW偏移3周)
如果Semana_LY和Semana_TW是固定线性关系(如LY = TW - 3),用sec_axis的转换函数实现:
library(ggplot2) ggplot(sales_data) + # 绘制本年销售额柱状图 geom_col(aes(x = Semana_TW, y = Ventas_TW), fill = "#2196F3", alpha = 0.7, width = 0.4) + # 绘制上年销售额柱状图,错开位置避免重叠 geom_col(aes(x = Semana_TW, y = Ventas_LY), fill = "#FF9800", alpha = 0.7, width = 0.4, position = position_nudge(x = 0.4)) + # 主X轴(下方:本年周数) scale_x_continuous( name = "Semana TW (本年周数)", breaks = sales_data$Semana_TW, # 次X轴(上方:上年周数),通过转换函数匹配对应关系 sec.axis = sec_axis( trans = ~ . - 3, name = "Semana LY (上年周数)", breaks = sales_data$Semana_LY ) ) + scale_y_continuous(name = "销售额") + labs(title = "近7周销售额对比(本年VS上年偏移3周)") + theme_minimal() + theme( axis.title.x.top = element_text(color = "#FF9800"), axis.title.x.bottom = element_text(color = "#2196F3"), legend.position = "top" ) + guides(fill = guide_legend(title = "销售额类型"))
自定义对应场景
如果Semana_LY和Semana_TW不是线性关系,用手动标签映射的方式实现:
# 提前定义TW到LY的对应关系 tw_to_ly <- setNames(sales_data$Semana_LY, sales_data$Semana_TW) ggplot(sales_data) + geom_col(aes(x = Semana_TW, y = Ventas_TW), fill = "#2196F3", alpha = 0.7, width = 0.4) + geom_col(aes(x = Semana_TW, y = Ventas_LY), fill = "#FF9800", alpha = 0.7, width = 0.4, position = position_nudge(x = 0.4)) + scale_x_continuous( name = "Semana TW (本年周数)", breaks = sales_data$Semana_TW, # 次X轴手动指定标签,完全匹配自定义对应关系 sec.axis = sec_axis( trans = ~ ., name = "Semana LY (上年周数)", breaks = sales_data$Semana_TW, labels = tw_to_ly ) ) + scale_y_continuous(name = "销售额") + labs(title = "近7周销售额对比(本年VS上年偏移3周)") + theme_minimal() + theme( axis.title.x.top = element_text(color = "#FF9800"), axis.title.x.bottom = element_text(color = "#2196F3"), legend.position = "top" ) + guides(fill = guide_legend(title = "销售额类型"))
关键说明
- 次X轴的核心是和主X轴的位置一一对应,不能独立映射另一组变量;
- 用
position_nudge错开两组柱状图,避免遮挡; - 跨年场景下(如TW第2周对应LY第51周),可调整转换函数为
~ ifelse(. <=3, . -3 +52, . -3)。
内容的提问来源于stack exchange,提问作者Francisco Augusto Varela Aguir
相关产品推荐
相关产品推荐

