Home > Blockchain >  Unable to display R Shiny DT inside tabPanel
Unable to display R Shiny DT inside tabPanel

Time:11-15

I'm unable to display a Shiny reactive DT within the tabPanel. May I know where the bug is?

The dataset is from Hong Kong Government. It is about the departure / arrival population from various control points since 2021: enter image description here

Also, may I know how to plot the graph showing the time changes using plotly? I only know how to plot in static version:

df %>%
  mutate(Date = as.Date(Date, format = "%d-%m-%Y")) %>%
  filter(`Control Point` == "Airport") %>%
  gather(Item, Count, `Hong Kong Residents`:Total) %>%
  ggplot(aes(
    x = Date,
    y = Count,
    fill = Item,
    color = `Arrival / Departure`
  ))  
  ggtitle("Daily passenger traffic")  
  scale_x_date(date_labels = "%y/%m", date_breaks  = "3 month")  
  theme(legend.position = "bottom")  
  geom_line()  
  facet_wrap( ~ Item)

Thank you for your help.

CodePudding user response:

Building on a couple of comments above.

Need to format your date in accordance with dateRangeInput() Need to filter with == rather than assignment operator <- Need to filter with column names in the dataframe

library(readr)
library(dplyr)
myData <- read_csv('...statistics_on_daily_passenger_traffic.csv')

#need to reorder and format the Date column
df <- myData %>%
  separate(Date, into = c('day', 'month', 'year'), sep = '-') %>% 
  unite(col = 'date', c(year, month, day), sep = '-') %>% 
  mutate(date = as.Date(date))

ui <-   fluidPage(
  titlePanel("Daily passenger traffic at control points in Hong Kong"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = 'control_point',
       label =  'Select Control Point',
       choices =  unique(df$`Control Point`)
      ),
      radioButtons(
       inputId =  'arrival_departure',
       label =  'Travel',
       choices =  unique(df$`Arrival / Departure`)
      ),
      dateRangeInput(
       inputId =  'date_range',
       label =  'Select Date',
       start = '2021-01-01',
       end = Sys.Date() - 1,
       min = '2021-01-01',
       max = Sys.Date() - 1
      )
    ),
    mainPanel(tabsetPanel(
      tabPanel('Hong Kong Residents', 
DT::DTOutput('plot_hk'),
 plotlyOutput('plot') #there are multiple ways to add plotly graphs
),
      tabPanel('Mainland Visitors'),
      tabPanel('Other Visitors'),
      tabPanel('Total')
    ))
  )
)

server <- function(input, output, session) {
  

  rval_plot_hk <- reactive({

      df %>% filter(
        date >= input$date_range[1],
        date <= input$date_range[2],
        `Control Point` == input$control_point, #your code had non-existent column names: control_point & arrival_departure
# your code needs == not assignment operating for filtering
        `Arrival / Departure` == input$arrival_departure
      )
    })

  output$plot_hk <- DT::renderDT({
    rval_plot_hk()
  })
  output$plot <- renderPlotly({
    
p <-     df %>%
      filter(`Control Point` == "Airport") %>%
      gather(Item, Count, `Hong Kong Residents`:Total) %>%
      ggplot(aes(
        x = date,
        y = Count,
        fill = Item,
        color = `Arrival / Departure`
      ))  
      ggtitle("Daily passenger traffic")  
      scale_x_date(date_labels = "%y/%m", date_breaks  = "3 month")  
      theme(legend.position = "bottom")  
      geom_line()  
      facet_wrap( ~ Item)

library(plotly)
ggplotly(p)

    
  })
  
}

shinyApp(ui, server)

CodePudding user response:

@Susan's solution works for me. But I also quickly worked through this:

The following should get your DT to display - you needed to get your date formatted correctly (as mentioned above) and you needed to filter according to the correct column names. Also change the reactive({}) call.

library(readr)
library(dplyr)

statistics_on_daily_passenger_traffic <-
  read_csv(
    "statistics_on_daily_passenger_traffic.csv"
  )
df <- statistics_on_daily_passenger_traffic
df <- df %>%
  select(-ncol(df)) %>%
  mutate(Date = as.Date(Date, format = '%d-%m-%Y')) %>%
  setNames(c('date', 'control_point', 'arrival_departure', 'HK', 'MV', 'OV', 'total')) #use effective names to match your filtering

library(shiny)
library(DT)


ui <-
  fluidPage(
    titlePanel("Daily passenger traffic at control points in Hong Kong"),
    sidebarLayout(
      sidebarPanel(
        selectInput(
          'control_point',
          'Select Control Point',
          unique(df$control_point) #have to change names to match above
        ),
        radioButtons(
          'arrival_departure',
          'Travel',
          unique(df$arrival_departure) #have to change names to match above
        ),
        dateRangeInput(
          'date_range',
          'Select Date',
          start = '2021-01-01',
          end = Sys.Date() - 1,
          min = '2021-01-01',
          max = Sys.Date() - 1
        )
      ),
      mainPanel(tabsetPanel(
        tabPanel('Hong Kong Residents', DTOutput('plot_hk')),
        tabPanel('Mainland Visitors'),
        tabPanel('Other Visitors'),
        tabPanel('Total')
      ))
    )
  )



server <- function(input, output, session) {
  rval_plot_hk <- reactive({
      df %>% filter(
        date >= input$date_range[1], #now your filtering names match your colnames for df
        date <= input$date_range[2],
        control_point == input$control_point, #you need '==' to filter, not assignment ('<-"). 
        arrival_departure == input$arrival_departure
      )
    })
  
  output$plot_hk <- renderDT(rval_plot_hk())
}


shinyApp(ui, server)

Regarding plotly you can simply wrap your plot in ggplotly() (as per @Susan's solution).

Note that for this to work you need to leave the names as you had them - i.e. not update them the way that I did. Also note that gather has been superseded by pivot_longer (https://tidyr.tidyverse.org/reference/gather.html).

library('ggplot2')
library('plotly')
library('tidyr')

ggplotly(df %>%
  mutate(Date = as.Date(Date, format = "%d-%m-%Y")) %>%
  filter(`Control Point` == "Airport") %>% #note that you call the filter verb correctly here, while you use assignment above
  gather(Item, Count, `Hong Kong Residents`:Total) %>%
  ggplot(aes(
    x = Date,
    y = Count,
    fill = Item,
    color = `Arrival / Departure`
  ))  
  ggtitle("Daily passenger traffic")  
  scale_x_date(date_labels = "%y/%m", date_breaks  = "3 month")  
  theme(legend.position = "bottom")  
  geom_line()  
  facet_wrap( ~ Item)) 
  • Related