在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 thelayout()parameters to match your needs.
内容的提问来源于stack exchange,提问作者Henk Straten
相关产品推荐
相关产品推荐

