Search code examples
rplotlyreactive

The interactive plot in plotly didn't appear in the rendered shinyApp page


I have an issue with making interactive plot in shinyApp. The data I have used is comprised 6 variables and 512 observations: Year, month, channel , viewCount , commentCount , likeCount. This is my reproducible code:

library(shiny)
library(shinyWidgets)
library(shinyjs)
library(plotly)
library(ggplot2)
library(thematic)
library(ragg)
library(showtext)


df <- read.csv(file_path)
thematic_shiny(font = "Pacifico")

ui <- fluidPage(
  
  # Select theme
  shinythemes::themeSelector(),
  
  tags$style(HTML("
    body {
      font-family: 'Pacifico', 15; /*Set up fonts for the page
  ")),
  
  # Fix widgets
  tags$head(
    tags$script(HTML('
       $(document).ready(function() {
        // Get the position of the sidebar
        var sidebarPosition = $(".sidebar").offset().top;

        // Function to fix or unfix the sidebar based on scrolling
        function fixSidebar() {
          var scrollTop = $(window).scrollTop();

          if (scrollTop > sidebarPosition) {
            $(".sidebar").addClass("fixed-sidebar");
          } else {
            $(".sidebar").removeClass("fixed-sidebar");
          }
        }

        // Attach the function to the scroll event
        $(window).scroll(fixSidebar);

        // Call the function once to set the initial state
        fixSidebar();
      });
    '))
  ),
  
  # Application title
  titlePanel("Youtube Data science Channels Analytics"),
  
  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(
      sliderTextInput(
        inputId = "year_slider",
        label = "Select Year",
        choices = as.character(2017:2024),
        selected = "2023",
        width = "300px"
      )
    )
  ),
    mainPanel(
      tabsetPanel(
        tabPanel('View Count', plotOutput('view_plot')),
        tabPanel('Comment Count', plotOutput('comment_plot')),
        tabPanel('Like Count', plotOutput('like_plot'))
    )
  )
)

server<-function(input, output) {
  
  
  library(dplyr)
  library(ggplot2)
  library(lubridate)
  
  df$channel <- as.factor(df$channel)
  
  #Filtering
  channel_pipeline <- reactive({
    
    df %>% 
      group_by(channel, Year) %>%
      summarize(
        viewCount = mean(viewCount), 
        commentCount = mean(commentCount), 
        likeCount = mean(likeCount)) %>% 
      arrange(Year, .by_group = T) %>% 
      filter(as.numeric(Year) %in% as.numeric(input$year_slider)) %>%
      as.data.frame()
  })
  
  # View Plot
  library(RColorBrewer)
  # Define color scale
  color_scale <- brewer.pal(length(unique(df$channel)), "Spectral")
  
  
  output$view_plot <- renderPlotly({
    channel_data <- channel_pipeline()
    print(head(isolate(channel_data())))   # Add this line for debugging
    
    plot_ly(data = channel_pipeline(), x = ~as.character(channel_pipeline()$channel), y = ~viewCount*1e-3, type = 'bar', color = ~as.character(channel_pipeline()$channel),
            colors = color_scale(length(unique(df$channel))))
    
    layout(xaxis = list(title = ''), yaxis = list(title = expresiom(10^3)))
    
    # Second approach to build an interactive plot
    # p1 <- ggplot(data = channel_pipeline(), aes(x = channel, y = viewCount*1e-3, fill = channel)) +
    #   geom_bar(stat = "identity", position = "dodge", width = 0.7, alpha = .8) +
    #   scale_fill_manual(values = RColorBrewer::brewer.pal(n = length(unique(df$channel)), name = 'Spectral')) +
    #   labs(title = "Videos performance by channels", x = "Channel") +
    #   scale_y_continuous(expression(10^3)) +
    #   theme_minimal() +
    #   theme(axis.text.x = element_text(angle = 0, vjust = 0.5, hjust = 1),
    #         axis.text.y = element_text(angle = 0, vjust = 0.5, hjust = 0.5),
    #         axis.title.y = element_text(angle = 0)) +
    #   scale_x_discrete(labels = function(x) {
    #     if (is.Date(x[1])) {
    #       format(x, "%Y")
    #     } else {
    #       x
    #     }
    #   })
    
    # ggplotly(p1)
    # p1
  })
  
  # Comments plot
  output$comment_plot <- renderPlotly({
    
    channel_data <- channel_pipeline()
    
    print(head(isolate(channel_data())))
    
    plotly(data = channel_data, x =~as.charater(channel_data()$channel), y =~commentCount*1e-3, color = as.character(channel_data()$channel), type = 'bar',
           colors = color_scale(length(unique(df$channel))))
    
    layout(xaxis = list(title = ''), yaxis = list(title = expresiom(10^3)))
    
    # Second approach to build an interactive plot
    # p2 <- ggplot(data = channel_pipeline(), aes(x = channel, y = commentCount*1e-3, fill = channel)) +
    #   geom_bar(stat = "identity", position = "dodge", width = 0.7, alpha =.8) +
    #   scale_fill_manual(values = RColorBrewer::brewer.pal(n = length(unique(df$channel)), name = 'Spectral')) +
    #   labs(title = "Videos performance by channels",
    #        x = "Channel"
    #   ) +
    #   scale_y_continuous(expression(10^3)) +
    #   theme_minimal() +
    #   theme(axis.text.x = element_text(angle = 0, vjust = 0.5, hjust = 1),
    #         axis.text.y = element_text(angle = 0, vjust = 0.5, hjust = 0.5),
    #         axis.title.y = element_text(angle = 0)) +
    #   scale_x_discrete(labels = function(x) {
    #     if (is.Date(x[1])) {
    #       format(x, "%Y")
    #     } else {
    #       x
    #     }
    #   })
    # 
    # # ggplotly(p2)
    # p2
  })
  
  # Likes plot
  output$like_plot <- renderPlotly({
    
    channel_data <- channel_pipeline()
    
    print(head(isolate(channel_data())))
    
    plotly(data = channel_data, x =~as.charater(channel_data()$channel), y =~likeCount*1e-3, color = as.character(channel_data()$channel), type = 'bar',
           colors = color_scale(length(unique(df$channel))))
    
    layout(xaxis = list(title = ''), yaxis = list(title = expresiom(10^3)))
    
    # Second approach to build an interactive plot
    # p3 <- ggplot(data = channel_pipeline(), aes(x = channel, y = likeCount*1e-3, fill = channel)) +
    #   geom_bar(stat = "identity", position = "dodge", width = 0.7, alpha =.8) +
    #   scale_fill_manual(values = RColorBrewer::brewer.pal(n = length(unique(df$channel)), name = 'Spectral')) +
    #   labs(title = "Videos performance by channels",
    #        x = "Channel"
    #   ) +
    #   scale_y_continuous(expression(10^3)) +
    #   theme_minimal() +
    #   theme(axis.text.x = element_text(angle = 0, vjust = 0.5, hjust = 1),
    #         axis.text.y = element_text(angle = 0, vjust = 0.5, hjust = 0.5),
    #         axis.title.y = element_text(angle = 0)) +
    #   scale_x_discrete(labels = function(x) {
    #     if (is.Date(x[1])) {
    #       format(x, "%Y")
    #     } else {
    #       x
    #     }
    #   })
    # ggplotly(p3)
    # p3
  }  
  )
  
})
  
shinyApp(ui, server)

I have tried to use ggplotly to convert ggplots into interactive charts, but I get only simple static plots.


Solution

  • When using plotly in Shiny, make sure to use plotlyOutput() in your UI and not just plotOutput() in order for your interactive graph to be displayed. Here is an adjustment to the mainPanel() of your app:

    mainPanel(
          tabsetPanel(
            tabPanel('View Count', plotlyOutput('view_plot')),
            tabPanel('Comment Count', plotlyOutput('comment_plot')),
            tabPanel('Like Count', plotlyOutput('like_plot'))
        )
      )
    )
    

    I hope it helps!