TomasD
TomasD

Reputation: 13

Shiny with dygraphs package

I am trying to use shiny with dygraphs. I try to produce a graph that would show time series data depending on the input variables. The sample of the data is the following:

     date      product sold
1  2015-01-01       a    1
2  2015-01-01       b   20
3  2015-02-01       a    2
4  2015-02-01       b   15
5  2015-03-01       a    3
6  2015-03-01       b   10
7  2015-04-01       a    4
8  2015-04-01       b    5
9  2015-05-01       a    5
10 2015-05-01       b    1

What I want is a time series graph with checkbox controls for the product variable (to see product a, b or both).

The ui and server code are (shinydashboard package):

library(shiny)
library(dygraphs)
library(dplyr)
library(xts)


ui <- dashboardPage(
skin="black",
dashboardHeader(title = "title"),
dashboardSidebar(
  sidebarMenu(
    menuItem("Results", tabName = "Result1", icon = icon("th"))
  )),
dashboardBody(
  tabItems(

    tabItem(tabName = "Result1",
            fluidRow(
              dygraphOutput("Graph")
            ),

            sidebarPanel(
              uiOutput("output1")
            )

    )

  ) )
 )

 server <- function(input, output) {


 output$Graph <- renderDygraph({

  data_f <- filter(data_products,
               product==input$type)
  xts(data_f$sold, as.Date(data_f$date, format = "%Y-%m-%d")) %>%
    dygraph()
  })
  output$output1<-renderUI({
  selectizeInput("type","Choose product",
   choices=levels(data_products$product), multiple=TRUE)
  })
   }

  shinyApp(ui, server)

tried several approaches but always get errors. Thanks in advance for any advice.

Upvotes: 1

Views: 782

Answers (1)

Michal Majka
Michal Majka

Reputation: 5471

You have to be careful in this part of the code:

data_f <- filter(data_products,
               product==input$type)

In this example, depending on your choices input$type can contain 0, 1 or 2 elements. If it contains one element "a" or "b" then everything is fine, however in other cases your going to get errors or warnings.

If you haven't selected any value in your widget, input$type is going to return NULL. Hence, logical comparison is going to fail and you are going to get errors. To avoid this it - before using the missing input - you can use req or validate functions which can be read as "require that an input is available" . Here you can read more about handling missing inputs in shiny.

If you selected both "a" and "b" product==input$type is going to return a warning because == doesn't work for multiple comparisions. Instead of this just change it to %in%.

Since you want a checkbox I changed selectInput to checkboxGroupInput


Full example:

library(shiny)
library(dygraphs)
library(dplyr)
library(xts)

# I pasted your example data to exces and then readed it into R with these 
# two lines of the code. It seems that product has to be a factor, because you
# use 'levels(data_products$product)'
# data_products <- as.data.frame(read_excel("~/Downloads/data.xlsx"))[-1]
# data_products$product <- as.factor(data_products$product)


ui <- dashboardPage(
  skin="black",
  dashboardHeader(title = "title"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Results", tabName = "Result1", icon = icon("th"))
    )),
  dashboardBody(
    tabItems(

      tabItem(tabName = "Result1",
              fluidRow(
                dygraphOutput("Graph")
              ),

              sidebarPanel(
                uiOutput("output1")
              )
      )
    )
  )
)

server <- function(input, output) {

  output$Graph <- renderDygraph({
    req(input$type) # require that input$type is available

    data_f <- filter(data_products,
                     product %in% input$type) # use "%in%" instead of "=="  
    xts(data_f$sold, as.Date(data_f$date, format = "%Y-%m-%d")) %>%
      dygraph()
  })
  output$output1 <- renderUI({
    # selectizeInput("type","Choose product",
    #                choices=levels(data_products$product), multiple=TRUE)
    checkboxGroupInput("type", "Choose product",
                       choices = levels(data_products$product),
                       selected = levels(data_products$product))
  })
}

shinyApp(ui, server)

EDITED:

If you want to have two lines when a and b are selected, you have to change the format of your data - you have to go from long to wide. The reason for that is that you can then easily create a bivariate time series with xts and dygraph will plot two separate lines.

Going from long to wide is easily accomplished with the reshape2 package from Hadley Wickham.

# Copy data from your example
data_products <- read.table(con<-file("clipboard"),header=T)
data_products$product <- as.factor(data_products$product)
# Reshape 
data_products <- dcast(data_products, date ~ product)

Your dataset looks now like this:

        date a  b
1 2015-01-01 1 20
2 2015-02-01 2 15
3 2015-03-01 3 10
4 2015-04-01 4  5
5 2015-05-01 5  1

Due to the new nature of the data, you have to slightly change the code on the server side. I left the comments in the code

ui <- dashboardPage(
  skin = "black",
  dashboardHeader(title = "title"),
  dashboardSidebar(
    sidebarMenu(
      menuItem("Results", tabName = "Result1", icon = icon("th"))
    )),
  dashboardBody(
    tabItems(

      tabItem(tabName = "Result1",
              fluidRow(
                dygraphOutput("Graph")
              ),

              sidebarPanel(
                uiOutput("output1")
              )
      )
    )
  )
)

server <- function(input, output) {

  output$Graph <- renderDygraph({
    req(input$type) # require that input$type is available

    # Due to the wide format we have to select columns
    data_f <- data_products[, c("date", input$type)]
    # univariate or bivariate time series
    xts(data_f[-1], as.Date(data_f$date, format = "%Y-%m-%d")) %>%
      dygraph()
  })

  output$output1 <- renderUI({
    # Since we now have data in wide format, the choices are 
    # the names of columns (expect date)
    checkboxGroupInput("type", "Choose product", 
                       choices = names(data_products)[-1])
  })
}

shinyApp(ui, server)

Upvotes: 1

Related Questions