Reputation: 13
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
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