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

在Shiny应用中将ggplot图表转成Plotly且保留柱状元素

Got it! Let's convert your ggplot-based Shiny app to use Plotly while preserving all bar chart elements. Below is a complete, working implementation based on your data setup, including filter buttons and the converted Plotly chart:

Full Shiny App with Plotly Bar Chart
library(shiny)
library(ggplot2)
library(plotly)
library(dplyr)

# Generate sample data (completed your partial code)
dates <- seq(as.Date("2018-01-01"), as.Date("2018-05-01"), by="days")
point_duration = rnorm(n=length(dates), mean=6, sd=1)
point_duration_bench = rnorm(n=length(dates), mean=5, sd=2)
df <- data.frame(dates, point_duration, point_duration_bench)
df$week <- strftime(df$dates, format = "%V")
df$month <- strftime(df$dates, format = "%m")
current_day = Sys.Date()
current_week = strftime(current_day, format = "%V")
current_month = strftime(current_day, format = "%m")

# UI with filter controls and Plotly output
ui <- fluidPage(
  titlePanel("Duration Comparison"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "time_filter",
        label = "Filter by:",
        choices = c("Day", "Week", "Month"),
        selected = "Day"
      )
    ),
    mainPanel(
      plotlyOutput("duration_plot")
    )
  )
)

# Server logic: Filter data, create ggplot, convert to Plotly
server <- function(input, output) {
  
  filtered_data <- reactive({
    if(input$time_filter == "Week") {
      df |> 
        group_by(week) |> 
        summarise(
          avg_duration = mean(point_duration),
          avg_bench = mean(point_duration_bench)
        )
    } else if(input$time_filter == "Month") {
      df |> 
        group_by(month) |> 
        summarise(
          avg_duration = mean(point_duration),
          avg_bench = mean(point_duration_bench)
        )
    } else {
      df |> 
        mutate(date_label = as.character(dates)) |> 
        select(date_label, point_duration, point_duration_bench) |> 
        rename(avg_duration = point_duration, avg_bench = point_duration_bench)
    }
  })
  
  output$duration_plot <- renderPlotly({
    # Create base ggplot bar chart with grouped bars
    p <- ggplot(filtered_data()) +
      geom_col(
        aes(x = if(input$time_filter == "Day") date_label else !!sym(input$time_filter), 
            y = avg_duration, fill = "Actual"), 
        position = position_dodge(width = 0.8), width = 0.35
      ) +
      geom_col(
        aes(x = if(input$time_filter == "Day") date_label else !!sym(input$time_filter), 
            y = avg_bench, fill = "Benchmark"), 
        position = position_dodge(width = 0.8), width = 0.35
      ) +
      labs(
        x = "Time Period",
        y = "Average Duration",
        fill = "Category"
      ) +
      theme_minimal() +
      theme(axis.text.x = element_text(angle = 45, hjust = 1))
    
    # Convert ggplot to Plotly while preserving all bar elements
    ggplotly(p) |> 
      layout(
        legend = list(title = list(text = "Category")),
        xaxis = list(title = "Time Period"),
        yaxis = list(title = "Average Duration")
      )
  })
}

shinyApp(ui = ui, server = server)

Key Details:

  • Bar Element Preservation: Using ggplotly() directly on your existing ggplot object automatically retains grouped bars, fill colors, and relative widths—no need to rebuild the chart from scratch in Plotly's native syntax.
  • Filter Consistency: The reactive filtered_data() function handles data aggregation exactly as your original app would, adjusting for day/week/month views seamlessly.
  • Interactive Tweaks: You can extend the Plotly output further (e.g., custom tooltips, hover text) by adding %>% add_trace() or modifying the layout() parameters to match your needs.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:26:34