You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny多选下拉场景下为不同指标折线配置对应线型的实现问题

问题描述
  • 目标是基于Shiny侧边栏下拉多选的指标,绘制点线结合的折线图
  • 线型规则要求:
    SellOut 对应的x、y字段使用实线(solid)
    GrossProfit 对应的x1、y1字段使用虚线(dashed)
    GrossSales 对应的x2、y2字段使用点线(dotted)
  • 现存问题:仅单个指标选中时可正常绘图,选中2个及以上指标时仅能渲染1条实线,无法展示多指标对应不同线型的折线,多选分支无有效绘图代码。
修复方案

核心修改点:

  1. 取消按选中指标数量分支写绘图逻辑的写法,提前建立指标、对应字段、线型的映射表
  2. 将宽格式的指标数据转为长格式,统一数据结构后,无论选中多少个指标都用同一套ggplot逻辑绘图
  3. 在线条映射中单独指定线型规则,保证不同指标严格匹配要求的线型,品牌颜色映射保持原有规则不变
修复后可运行完整代码
library(shiny)
library(shinydashboard)
library(plotly)
library(tidyr)
library(dplyr)
library(DT)
library(ggplot2)

BRAND<-c("CHOKIS","CHOKIS","CHOKIS","CHOKIS","CHOKIS","CHOKIS","LARA CHOCO CHIPS","LARA CHOCO CHIPS","LARA CHOCO CHIPS")
BRAND_COLOR<-c("#8050f0","#8050f0","#8050f0","#8050f0","#8050f0","#8050f0","#f050c0","#f050c0","#f050c0")

SellOut.x<-c(23,34,56,77,78,34,34,64,76)
SellOut.y<-c(43,54,76,78,87,98,76,76,56)
GrossProfit.x1<-c(23,34,56,75,78,34,34,64,76)
GrossProfit.y1<-c(33,54,76,76,87,98,76,76,56)
GrossSales.x2<-c(53,34,56,77,78,34,34,84,76)
GrossSales.y2<-c(63,54,76,78,87,98,76,76,86)
r<-c(58,46,76,76,54,21,69,98,98)

graph1.data<-data.frame(BRAND,BRAND_COLOR,r)
df6 <- data.frame(SellOut.x, SellOut.y, GrossProfit.x1, GrossProfit.y1, GrossSales.x2, GrossSales.y2) 

# 提前配置指标和字段、线型的映射规则
metric_config <- data.frame(
  metric_input = c("Sell Out", "Gross Profit", "Gross Sales"),
  metric_col = c("SellOut", "GrossProfit", "GrossSales"),
  x_col = c("x", "x1", "x2"),
  y_col = c("y", "y1", "y2"),
  line_type = c("solid", "dashed", "dotted")
)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    selectInput("metric","Metric",c('Gross Sales','Gross Profit','Sell Out'),multiple = T,selected = "Sell Out")
  ),
  dashboardBody(
    DTOutput("df"),
    plotlyOutput("plot")
  )
)

server <- function(input, output) {
  
  reactiveDf <- reactive({
    req(input$metric)
    # 匹配选中的指标对应的配置
    selected_config <- metric_config[metric_config$metric_input %in% input$metric, ]
    
    # 提取对应字段转长表
    plot_data <- lapply(1:nrow(selected_config), function(i){
      tmp_config <- selected_config[i, ]
      x_col_name <- paste0(tmp_config$metric_col, ".", tmp_config$x_col)
      y_col_name <- paste0(tmp_config$metric_col, ".", tmp_config$y_col)
      data.frame(
        BRAND = graph1.data$BRAND,
        BRAND_COLOR = graph1.data$BRAND_COLOR,
        r = graph1.data$r,
        metric = tmp_config$metric_input,
        x = df6[[x_col_name]],
        y = df6[[y_col_name]],
        line_type = tmp_config$line_type
      )
    }) %>% bind_rows()
    
    return(plot_data)
  })
  
  output$df<-renderDT({
    reactiveDf()
  })
  
  output$plot<-renderPlotly({
    Df <- req(reactiveDf())
    # 品牌颜色映射
    brand.colors <- unique(Df[,c("BRAND","BRAND_COLOR")])
    color_vals <- brand.colors$BRAND_COLOR
    names(color_vals) <- brand.colors$BRAND
    # 线型映射
    linetype_vals <- c("solid"="solid", "dashed"="dashed", "dotted"="dotted")
    
    p <- ggplot(Df, aes(x=x, y=y, color=BRAND, linetype=line_type, group=interaction(BRAND, metric))) +
      geom_line(linewidth=1) +
      geom_point(aes(size=r), show.legend=TRUE) +
      scale_color_manual(values=color_vals) +
      scale_linetype_manual(values=linetype_vals, labels=c("实线(Sell Out)","虚线(Gross Profit)","点线(Gross Sales)")) +
      labs(linetype="指标类型", color="品牌", size="r值") +
      theme_minimal()
    
    ggplotly(p)
  })
}

shinyApp(ui, server)
效果说明
  • 选中任意数量指标都可正常渲染,每个品牌对应固定颜色
  • 不同指标严格匹配预设线型:Sell Out为实线、Gross Profit为虚线、Gross Sales为点线
  • 点的大小保持原有映射r值的规则,表格输出同步展示绘图所用的长格式数据

内容的提问来源于stack exchange,提问作者firmo23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 04:31:05