如何在Shiny中将autoplot生成的两个序列合并为共享Y轴的双X轴图?
实现双Y轴对比Box-Cox转换前后的数据序列
需求说明
原本用autoplot()生成了两个独立图表:一个随滑块输入的lambda值动态展示Box-Cox转换后的序列,另一个静态展示原始序列。现在需要将两者合并到同一图表中,左侧Y轴(主轴)显示转换后的数据(随lambda变化),右侧Y轴(副轴)固定显示原始数据,X轴统一为月份,方便直观对比转换对数据形态的影响。
解决方案代码
library(feasts) library(fabletools) library(ggplot2) library(shiny) library(tsibble) library(latex2exp) # 构造数据 DF <- data.frame( Month = c(1:12), StateX = c(59,77,45,42,32,26,27,21,19,22,24,10) ) DF1 <- DF %>% as_tsibble(index = Month) ui <- fluidPage( sliderInput("lambda","Transformation lambda:",min=-2,max=2,value=0.5,step = 0.1), plotOutput("combinedPlot") # 只保留一个绘图输出 ) server <- function(input, output) { output$combinedPlot <- renderPlot({ # 计算转换后的数据 transformed_data <- DF1 %>% mutate(Transformed = box_cox(StateX, input$lambda)) # 手动构建ggplot,实现双Y轴 ggplot(transformed_data, aes(x = Month)) + # 绘制转换后的数据(主Y轴) geom_line(aes(y = Transformed, color = "Transformed"), linewidth = 1) + # 绘制原始数据(副Y轴) geom_line(aes(y = StateX, color = "Original"), linewidth = 1) + # 添加副Y轴,直接映射原始数据值 scale_y_continuous( name = "Transformed Values", sec.axis = sec_axis(~., name = "Original Values") ) + scale_color_manual(values = c("Transformed" = "#2E86AB", "Original" = "#F24C4C")) + labs( title = TeX(paste0("Box-Cox Transformed vs Original StateX ($\\lambda = ", round(input$lambda,2), "$)")), x = "Month", color = "Series" ) + theme_minimal() + theme(plot.title = element_text(hjust = 0.5)) }) } shinyApp(ui, server)
关键实现要点
- 放弃
autoplot()的自动绘图,手动构建ggplot图层以灵活控制双轴配置 - 提前用
mutate()计算转换后的数据,简化图层调用逻辑 - 通过
scale_y_continuous()的sec.axis参数添加右侧副Y轴,直接映射原始数据范围 - 用
scale_color_manual()为两个序列设置不同颜色,提升辨识度 - 借助
latex2exp在标题中渲染lambda的数学符号,表述更专业
内容的提问来源于stack exchange,提问作者Village.Idyot
相关产品推荐
相关产品推荐

