Shiny scatterplot with real-time Kaplan-Meier - r

I have constructed an interactive scatterplot in Shiny. Using plotly, I can select groups of points and render the annotations for this group in a table next to the plot.
library(survival)
library(survminer)
mtcars <- get(data("mtcars"))
attach(mtcars)
mtcars$OS <- sample(100, size = nrow(mtcars), replace = TRUE)
mtcars$status <- sample(0:1, size = nrow(mtcars), replace = TRUE)
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("Test1", tabName = "test1"),
menuItem("Test2", tabName = "test2"),
menuItem("Test3", tabName = "test3"),
radioButtons("radio", h3("Choose groups"),
choices = list("Group 1" = 1, "Group 2" = 2,
"Group 3" = 3),selected = 1),
actionButton("action", "Reset")
)
),
dashboardBody(
tabItems(
tabItem(tabName = "test1",
fluidRow(
column(6,plotlyOutput("plot")),
column(width = 6, offset = 0,
DT::dataTableOutput("brush"),
tags$head(tags$style("#brush{font-size:11px;}")))
)
)
)
)
)
server <- shinyServer(function(input, output, session) {
output$plot <- renderPlotly({
key <- row.names(mtcars)
p <- ggplot(data=mtcars, aes(x=wt,y=mpg,key=key)) +
geom_point(colour="grey", size=2, alpha=1, stroke=0.5)
ggplotly(p) %>% layout(height = 500, width = 500, dragmode = "select")
})
output$brush <- DT::renderDataTable({
d <- event_data("plotly_selected")
req(d)
DT::datatable(mtcars[unlist(d$key), c("mpg", "cyl", "OS", "status")],
options = list(lengthMenu = c(5, 30, 50), pageLength = 30))
}
)
})
shinyApp(ui, server)
Example:
enter image description here
I would like to be able to select (lasso or rectangle) groups of points and display the survival curves between these groups (and p-value if possible) in a separate plot below the table. For example, the user would select 'Group1' on the menu to the left, then outline the desired groups of points, then selct 'Group 2' and select a second group of points, and so on. After each selection, the survival curves appear below the table. Once finished (and would like to restart a new comparison, the user hits 'Reset'). Here's an example output:
Example:
Expected Shiny output
I really don't know where to begin with how to incorporate this. Any help would be great, thank you

See the code below for one possible way to implement this. Throughout, rv is a reactiveValues object holding the data in a data.frame data_df. The group column in data_df tracks group membership as points are selected in the plot, and takes values of 1, 2, 3, or NA depending on whether the row is in one of the three groups. (Note: the groups are assumed to be non-overlapping.)
When the user changes the radio button selection, the plotly selection rectangle should disappear in order to prepare for the selection of the next set of points - the code below uses the shinyjs library to accomplish this, as well as to reset plotly_selected to NULL (otherwise the next rectangular selection will fail to register if it selects the same set of points as the previous one).
library(survival)
library(survminer)
library(plotly)
library(shiny)
library(shinydashboard)
library(shinyjs)
mtcars <- get(data("mtcars"))
attach(mtcars)
mtcars$OS <- sample(100, size = nrow(mtcars), replace = TRUE)
mtcars$status <- sample(0:1, size = nrow(mtcars), replace = TRUE)
jsCode <- "shinyjs.resetSel = function() { Plotly.restyle(plot, {selectedpoints: [null]});}"
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("Test1", tabName = "test1"),
menuItem("Test2", tabName = "test2"),
menuItem("Test3", tabName = "test3"),
radioButtons("radio", h3("Choose groups"),
choices = list("Group 1" = 1, "Group 2" = 2,
"Group 3" = 3), selected = 1),
actionButton("action", "Reset all Groups"),
br(),
uiOutput("currentSelections")
)
),
dashboardBody(
useShinyjs(),
extendShinyjs(text = jsCode, functions = c("resetSel")),
tabItems(
tabItem(tabName = "test1",
fluidRow(
column(6,plotlyOutput("plot")),
column(width = 6, offset = 0,
DT::dataTableOutput("brush"),
tags$head(tags$style("#brush{font-size:11px;}")))
),
fluidRow(
column(6),
column(6, plotOutput("survivalCurve"))
)
)
)
)
)
server <- shinyServer(function(input, output, session) {
## mtcars data.frame with an extra group column (initially set to NA)
rv <- reactiveValues(data_df = mtcars %>% mutate(group = NA))
## when a selection is made, assign group values to data_df based on selected radio button
observeEvent(
event_data("plotly_selected"), {
d <- event_data("plotly_selected")
## reset values for this group
rv$data_df$group <- ifelse(rv$data_df$group == input$radio, NA, rv$data_df$group)
## then re-assign values:
rv$data_df[d$key,"group"] <- input$radio
}
)
## when reset button is pressed, reset the selection rectangle
## and also reset the group column of data_df to NA
observeEvent(input$action, {
js$resetSel()
rv$data_df$group <- NA
})
## when radio button changes, reset the selection rectangle and reset plotly_selected
## (otherwise selecting the same set of points for two groups consecutively will
## not register the selection the second time)
observeEvent(input$radio, {
js$resetSel()
runjs("Shiny.setInputValue('plotly_selected-A', null);")
})
## draw the main plot
output$plot <- renderPlotly({
key <- row.names(mtcars)
p <- ggplot(data=mtcars, aes(x=wt,y=mpg,key=key)) +
geom_point(colour="grey", size=2, alpha=1, stroke=0.5)
ggplotly(p) %>% layout(height = 500, width = 500, dragmode = "select")
})
## for each group, show the number of selected points
## (not required by the rest of the app but useful for debugging)
output$currentSelections <- renderUI({
number_by_class <- summary(factor(rv$data_df$group, levels = c("1","2","3")))
tagList(
h5("Current Selections:"),
p(paste0("Group 1: ",number_by_class[1], " points selected")),
p(paste0("Group 2: ",number_by_class[2], " points selected")),
p(paste0("Group 3: ",number_by_class[3], " points selected"))
)
})
output$brush <- DT::renderDataTable({
d <- event_data("plotly_selected")
req(d)
DT::datatable(mtcars[unlist(d$key), c("mpg", "cyl", "OS", "status")],
options = list(lengthMenu = c(5, 30, 50), pageLength = 30))
})
## draw survival curves if a point has been selected
## if none have been selected then draw a blank plot with matching background color
output$survivalCurve <- renderPlot({
if (any(c(1,2,3) %in% rv$data_df$group)) {
fit <- survfit(Surv(mpg, status) ~ group,
data = rv$data_df)
ggsurvplot(fit, data = rv$data_df, risk.table = FALSE)
} else {
par(bg = "#ecf0f5")
plot.new()
}
})
})
shinyApp(ui, server)

Related

How to filter a column in shiny whose name is an output from a slider

I have a dashboard where slider is getting updated based on a dropdown widget. My issue is that dropdown selects the name of the column, and slider filters the selected column. The issue is when i create reactive filtered dataset: specifically this line: filter(input$selectx > input$my_slider[1]. i understand that it does not work cause the input$selectx is a character name of the column (eg "mean_radius", and I need a name without quotations (eg mean_radius). I tried quote(), {{}} and other functions but could not sort it out
#loading packages
library(shiny)
library(tidyverse)
library(datateachr) #cancer_sample dataset was used from this data package
library(rstatix)
library(shinythemes)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Cancer", titleWidth = 300),
dashboardSidebar(
width = 300,
selectInput("selectx", label = h3("Select X Variable"),
choices = list("radius_mean", "texture_mean", "perimeter_mean", "area_mean"),
selected = "area_mean"),
tags$br(),
sliderInput("my_slider",
label = h3("Range of X Variable"),
min = min(cancer_sample$area_mean, na.rm = TRUE),
max = max(cancer_sample$area_mean, na.rm = TRUE),
value = c(143.5,2501))
),
dashboardBody(
#makes the place holder for the plot
box(title = "Scatter Plot", solidHeader = TRUE, collapsible = TRUE, width = 12, plotOutput("my_plot", click = "plot_click")),
box(title = "Data Table", solidHeader = TRUE, collapsible = TRUE, width = 12, tableOutput("my_data"))
)
)
server <- function(input, output, session) {
#makes a reactive function to minimize repeated code
filtered <- reactive({
#the dataset that is being used
cancer_sample %>%
#filters the data set based on the area mean range from the slider, and the check boxes that are selected
filter(input$selectx > input$my_slider[1],
input$selectx < input$my_slider[2])
})
observe({
col <- cancer_sample %>% select(input$selectx)
#makes a slider that you can manipulate to show only data points that has an area mean that falls in the certain range
updateSliderInput(session, "my_slider",
value = col,
min = min(col, na.rm = TRUE),
max = max(col, na.rm = TRUE))
})
output$my_plot <- renderPlot({
filtered() %>%
#produces a graph with area_mean on the x-axis and perimeter_mean on the y-axis.
ggplot(aes_string(x = input$selectx, y = perimeter_mean)) +
geom_point(aes(colour = diagnosis))
})
output$my_data <- renderTable(
filtered() %>%
select(ID:area_mean)
)
}
# Run the application
shinyApp(ui = ui, server = server)
Your problem is not shiny connected, so the question could be easily simplified.
Unfortunately you do not provide the dataset here. So I could not provide a working example.
quote will always return what is inside quote(input$selectx) -> input$selectx so this for sure not a solution.
Please use the e.g. .data solution here.
airquality %>% filter(.data[[input$selectx]] > input$my_slider[1],
.data[[input$selectx]] < input$my_slider[2])

Format table output in R shiny based on user inputs

I have a table being display in a shiny app. I want to format the tables based on the values and color it accordingly. I have seen the formattable area coloring where based on the range of the values it defines the breaks and then color gradients are generated which are applied to the table. What I want to do is allow the user to fill the min and max value and depending on it the values in the table will be colored. So if the values range from 1-20 and if the user inputs are 5 and 15 , values below 5 and above 15 shouldnt have any color gradients applied to them. Below is the code of how I am doing currently using formatable area formatting.
library(shiny)
library(shinyWidgets)
library(shinydashboard)
library(DT)
sidebar <- dashboardSidebar(
sidebarMenu(id = "tab",
menuItem("1", tabName = "1")
)
)
body <- ## Body content
dashboardBody(box(width = 12,fluidRow(
fluidRow( column(
width = 3, textInput("text1", label = h5("Min"), value = "Enter min")),
column(
width = 3, textInput("text2", label = h5("Max"), value = "Enter max"))),
DT::dataTableOutput("op")
)))
ui <- dashboardPage(dashboardHeader(title = "Scorecard"),
sidebar,
body)
# Define the server code
server <- function(input, output,session) {
df <- data.frame(month = c("mazda 3", "mazda cx5", "mazda 6","mazda miata","honda civic","honda accord"),
april = c(.1,.2,.3,.3,.4,.5),
may = c(.3,.4,.5,.2,.1,.5),
june = c(.2,.1,.5,.1,.2,.3))
brks <- reactive({ quantile(df$april, probs = seq(.05, .95, .05), na.rm = TRUE)})
clrs <- reactive({ round(seq(255, 175, length.out = length(brks()) + 1), 0) %>%
{paste0("rgb(",.,",", ., ",255 )")}})
df_format<- reactive ({datatable(df,options = list(searching = FALSE,pageLength = 15, lengthChange = FALSE))%>%
formatStyle(names(df),backgroundColor = styleInterval(brks(), clrs()))})
output$op <-renderDataTable({
df_format()
})
}
shinyApp(ui = ui, server = server)
Here is your working code.
You must use that input minimal and maximal value as limits for your sequence (I just change it to range - is easier for user to put a range like that)
Then you generate sequence - according your notation - brks() - in my case I use length.out of 10 but you can put as many breaks as you want or dynamically.
Then generate on
number of colors - 1
and in the end in styleInterval() for background add limits of white - or any other color you want.
library(shiny)
library(shinyWidgets)
library(shinydashboard)
library(DT)
sidebar <- dashboardSidebar(
sidebarMenu(id = "tab",
menuItem("1", tabName = "1")
)
)
body <- ## Body content
dashboardBody(box(width = 12,fluidRow(
fluidRow(column(
width = 3,
sliderInput("range_value",
label = h3("Put a range value"),
min = 0,
max = 100,
value = c(5, 15)
)
)
),
DT::dataTableOutput("op")
)))
ui <- dashboardPage(dashboardHeader(title = "Scorecard"),
sidebar,
body)
# Define the server code
server <- function(input, output,session) {
df <- data.frame(month = c("mazda 3", "mazda cx5", "mazda 6","mazda miata","honda
civic","honda accord"),
april = c(9, 8, 11,14,16,1),
may = c(3,4,15,12,11, 19),
june = c(2,11,9,7,14,1))
brks <- reactive({
seq(input$range_value[1], input$range_value[2], length.out = 10)
})
clrs <- reactive({ round(seq(255, 175, length.out = length(brks()) - 1), 0) %>%
{paste0("rgb(",.,",", ., ",255)")}})
df_format<- reactive ({datatable(df,options = list(searching = FALSE, pageLength = 15, lengthChange = FALSE)) %>%
formatStyle(names(df),
backgroundColor = styleInterval(c(brks()), c('white', clrs() ,'white'))
)
})
output$op <-renderDataTable({
df_format()
})
}
shinyApp(ui = ui, server = server)

Change google maps heatmap options in shiny

I am using googleway library in Shiny R.
The heatmap displays correctly, but I cannot change the heatmap options. If I uncomment the block code where I try to change options, the app crashes.
Here is the part of the code that works, with the offending lines commented out.
library(googleway)
library(magrittr)
library(shiny)
library(shinydashboard)
# Define UI for app
header1 <- dashboardHeader(
title = "My Dashboard"
)
sidebar1 <- dashboardSidebar(
sidebarMenu(
fileInput("file0", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",".csv")),
sliderInput("opacity", "Opacity:",
min = 0, max = 1,
value = 0.5, step = 0.05),
sliderInput("radius", "Radius:",
min = 0, max = 50,
value = 25),
sliderInput("blur", "Blur:",
min = 0, max = 1,
value = 0.75, step = 0.05),
sliderInput("maxvalue", "MaxValue:",
min = 0, max = 1,
value = 1, step = 0.05)
) #sidebarMenu
) #dashboardSidebar
body1 <- dashboardBody(
fluidRow(
tabBox(
title = "TabBox Title 1",
id = "tabset1", height = "400px", width = 11,
selected = "Tab1",
tabPanel("Tab1",
google_mapOutput("Map1")
),
tabPanel("Tab2", "Tab content 2")
) #box
) #fluidRow
) #dashboardBody
ui <- dashboardPage(header1, sidebar1, body1)
# Define data
df <- data.frame(lat = c(14.61),
lon = c(-90.54),
weight = c(100))
# Define SERVER logic
server <- function(input, output, session) {
map_key <- "my_key"
## https://developers.google.com/maps/documentation/javascript/get-api-key
## plot the map
output$Map1 <- renderGoogle_map({
google_map(key = map_key, data = df, zoom = 2, search_box = F) %>%
add_heatmap(weight = "weight") #%>%
#add_traffic()
}) #renderGoogle_map
observeEvent(input$opacity, {
# THIS PART IS COMMENTED OUT BECAUSE THE APP CRASHES
# google_map_update(map_id = "Map1") %>%
# update_heatmap(data = df, option_opacity = input$opacity)
}) #observeEvent
} #server
# Run app
shinyApp(ui, server)
Your help with this will be greatly appreciated! :)
You can use a reactive({}) to carry the input$opacity value and pass it directly to add_heatmap() to achieve the opacity responsiveness.
This can still be done inside the google_map_update(), but you'd have to clear the heatmap layer first, otherwise you'd just be adding layers on top of each other.
server <- function(input, output, session) {
map_key <- "your_key"
## https://developers.google.com/maps/documentation/javascript/get-api-key
opacity <- reactive({
return(input$opacity)
})
## plot the map
output$Map1 <- renderGoogle_map({
google_map(key = map_key, data = df, zoom = 2, search_box = F) %>%
add_heatmap(weight = "weight") #%>%
#add_traffic()
}) #renderGoogle_map
observeEvent(input$opacity, {
google_map_update(map_id = "Map1") %>%
clear_heatmap() %>%
add_heatmap(data = df, option_opacity = opacity())
})
}
} #server

create empty dygraph in Rshiny

I'm using Dygraphs package for visualizing actual and the time series predicted values in R shiny. Here is the sample code that I used to generate the Dygraph. In some cases where the data points are less Holt Winters(gamma =T) does not give any prediction and I need to show an empty Dygraph with the title "Insufficient Data"). I'm not able to do this. Appreciate any help on this
library(dygraphs)
plotDyg <- fluidPage(
fluidRow(
box(selectizeInput("c1", "Enter a key",
choices = reactive({sort(unique(df$key))})(),
multiple = FALSE),width=3),
box(dygraphOutput("tsDy"), width = 10, height = 500))
)
ui <- dashboardPage(
dashboardHeader(title = "XYZ"),
dashboardSidebar(
sidebarMenu(
menuItem("abc", tabName = "sidebar2", icon = icon("bar-chart") ,
menuSubItem("def",icon = icon("folder-open"), tabName = "subMenu1")
)
)
),
dashboardBody(
tabItems(
tabItem(tabName = "subMenu1",
fluidRow(
tabBox(
title = "ghi", id = "tabset2",height = "1500px",width = 100,
tabPanel("abcdef", plotDyg)
)
)
)
)
)
)
server <- function(input, output) {
output$tsDy <- renderDygraph({
if(!is.null(input$c1)){
df.0 <- reactive({df[df$key == input$c1,]})()
tspred <- reactive({
df.0 <- convert_to_ts(df.0) # converts column "fin_var" to a monthly time series and returns the entire dataframe
act <- df.0$fin_var
hw <- tryCatch(HoltWinters(df.0$fin_var), error=function(e)NA)
if(length(hw) > 1){
p <- predict(hw, n.ahead = 12, prediction.interval = TRUE, level = 0.95)
all1 <- cbind(act, p)
}else{all1 <- matrix()}
})
if(!is.na(tspred())){
dygraph(tspred(), main = "TS Predictions") %>%
dySeries("act", label = "Actual") %>%
dySeries(c("p.lwr", "p.fit", "p.upr"), label = "Predicted") %>%
dyOptions(drawGrid = F) %>%
dyRangeSelector()
}else{dygraph(matrix(0), main = "Insufficient Data")} # I could just do 'return()' but I want to show an empty Dygraph with the title
}else{return()}
})
}
I too am unable to render Dygraphs with an empty time series. To render a message to the user I used the validate/need functions in Shiny
In your case I would replace
if(!is.na(tspred())){
With
validate(need(!is.na(tspred())), "Insufficient Data"))
This will avoid the "error: argument is of length zero" message within Dygraphs and print an appropriate message to the end user.

ShinyApp errors: selectInput, data-subsetting

I am creating shiny app. My goal is to visualize some data slices depending on the input.I am quite happy with the result.
However, my app has a few bugs while the app is loading. Before ploting the graph and visualizing inputs it shows some errors on screen (you can lauch the app and see the problem).
I believe, the first problem is with data filtering. I can't figure out how to deal with it and what is the problem. May I need to use other method or maybe other package? (see the output$Brand).
Error in grep(pattern, levels(vector)) : invalid 'pattern' argument
The second error comes when I am creating selectInput. I'd like to visualize all the brands of the specific category in one plot and to have an option to filter data by brand. However, my method is not working well. Any suggestions? (see the output$Brand).
Error in if (input$Brand == "All") { : argument is of length zero
Also, I enclose the code, which you can generate.
May you have any more suggestions how to simplify the code?
Thanks for the help!
library(shiny)
library(shinydashboard)
library(data.table)
library(ggplot2)
library(grid)
library(scales)
library(ggthemes)
# Header -----------------------------------------------------------
header <- dashboardHeader(title="Dashboard")
# Sidebar --------------------------------------------------------------
sm <- sidebarMenu(
menuItem(
text="Graph1",
tabName="Graph1",
icon=icon("home")
)
)
sidebar <- dashboardSidebar(sm)
# Body --------------------------------------------------
body <- dashboardBody(
# Layout --------------------------------------------
tabItems(
tabItem(
tabName="Graph1",
fluidPage(
fluidRow(
box(
title = "Inputs", status = "warning", width = 2, solidHeader = TRUE,
uiOutput("Year"),
uiOutput("Category"),
uiOutput("Brand"),
sliderInput("Finalas.Range", "Months:",
min = 1, max = 12, value = c(1,12))
),
box(
title = "Season", width = 10, status = "info", solidHeader = TRUE,
plotOutput("Graph1")
)
)
)
)
)
)
# Setup Shiny app UI components -------------------------------------------
ui <- dashboardPage(header, sidebar, body, skin="black")
# Setup Shiny app back-end components -------------------------------------
server <- function(input, output) {
# Generate data --------------------------------------
set.seed(1992)
n=99
Year <- sample(2013:2015, n, replace = TRUE, prob = NULL)
Month <- sample(1:12, n, replace = TRUE, prob = NULL)
Category <- sample(c("Car", "Bus", "Bike"), n, replace = TRUE, prob = NULL)
Brand <- sample("Brand", n, replace = TRUE, prob = NULL)
Brand <- paste0(Brand, sample(1:14, n, replace = TRUE, prob = NULL))
USD <- abs(rnorm(n))*100
df <- data.frame(Year, Month, Category, Brand, USD)
# Inputs --------------------------------------
output$Year <- renderUI({
selectInput("Year",
"Year:",
c(unique(as.character(df$Year))), selected = "2015")
})
output$Category <- renderUI({
selectInput("Category", "Choose category:",
choices = c("Car","Bus", "Bike" ))
})
output$Brand <- renderUI({
df2 <- (data.table(df))[like(df$Category,input$Category)]
selectInput("Brand",
"Brand:",
c("All", unique(as.character(df2$Brand))))
})
# Plot --------------------------------
output$Graph1 <- renderPlot({
df <- data.table(df)
if (input$Brand == "All") {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)+
scale_fill_gdocs(guide = guide_legend(title = "Brand"))
} else {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
df <- df[which(df$Brand == input$Brand),]
validate(
need(sum(df$USD)>0, paste(input$Brand, "was inactive in Year:",input$Year))
)
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)
}
})
# -----------------------------------------------------------------------------
}
# Render Shiny app --------------------------------------------------------
shinyApp(ui, server)
The following should eliminate these errors: for #1 the function like in datatable gives out the error so I changed it to %in% instead. and for #2 you have a null as a default so take care of that with an if statement
rm(list = ls())
library(shiny)
library(shinydashboard)
library(data.table)
library(ggplot2)
library(grid)
library(scales)
library(ggthemes)
# Header -----------------------------------------------------------
header <- dashboardHeader(title="Dashboard")
# Sidebar --------------------------------------------------------------
sm <- sidebarMenu(
menuItem(
text="Graph1",
tabName="Graph1",
icon=icon("home")
)
)
sidebar <- dashboardSidebar(sm)
# Body --------------------------------------------------
body <- dashboardBody(
# Layout --------------------------------------------
tabItems(
tabItem(
tabName="Graph1",
fluidPage(
fluidRow(
box(
title = "Inputs", status = "warning", width = 2, solidHeader = TRUE,
uiOutput("Year"),
uiOutput("Category"),
uiOutput("Brand"),
sliderInput("Finalas.Range", "Months:",
min = 1, max = 12, value = c(1,12))
),
box(
title = "Season", width = 10, status = "info", solidHeader = TRUE,
plotOutput("Graph1")
)
)
)
)
)
)
# Setup Shiny app UI components -------------------------------------------
ui <- dashboardPage(header, sidebar, body, skin="black")
# Setup Shiny app back-end components -------------------------------------
server <- function(input, output) {
# Generate data --------------------------------------
set.seed(1992)
n=99
Year <- sample(2013:2015, n, replace = TRUE, prob = NULL)
Month <- sample(1:12, n, replace = TRUE, prob = NULL)
Category <- sample(c("Car", "Bus", "Bike"), n, replace = TRUE, prob = NULL)
Brand <- sample("Brand", n, replace = TRUE, prob = NULL)
Brand <- paste0(Brand, sample(1:14, n, replace = TRUE, prob = NULL))
USD <- abs(rnorm(n))*100
df <- data.frame(Year, Month, Category, Brand, USD)
# Inputs --------------------------------------
output$Year <- renderUI({
selectInput("Year",
"Year:",
c(unique(as.character(df$Year))), selected = "2015")
})
output$Category <- renderUI({
selectInput("Category", "Choose category:",
choices = c("Car","Bus", "Bike" ))
})
output$Brand <- renderUI({
# first error
#df2 <- (data.table(df))[like(df$Category,input$Category)]
df2 <- df[df$Category %in% input$Category,]
selectInput("Brand",
"Brand:",
c("All", unique(as.character(df2$Brand))))
})
# Plot --------------------------------
output$Graph1 <- renderPlot({
df <- data.table(df)
if(is.null(input$Brand) || is.na(input$Brand)){return()}
else if (input$Brand == "All") {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)+
scale_fill_gdocs(guide = guide_legend(title = "Brand"))
} else {
df <- df[like(df$Year, input$Year)]
df <- df[like(df$Category,input$Category)]
df <- df[which(df$Brand == input$Brand),]
validate(
need(sum(df$USD)>0, paste(input$Brand, "was inactive in Year:",input$Year))
)
ggplot(df, aes(x=factor(Month,levels=1:12), y=USD, fill=Brand))+
geom_bar(stat='identity')+
scale_x_discrete('Month', breaks=factor(1:12), drop=FALSE)
}
})
# -----------------------------------------------------------------------------
}
# Render Shiny app --------------------------------------------------------
shinyApp(ui, server)

Resources