I am trying to create small application using Shiny. Below is the data frame for which I am trying to create.
data<-data.frame(state=c('AZ','VA','CA','AZ','VA','CA'), city=c('Phoenix','Arlington','SantaClara','Mesa','Richmond','SF'),
avg=c(10,15,16,13,14,14), date=c('01/09/2017','01/10/2017','01/11/2017','02/09/2017','02/10/2017','02/10/2017'),stringsAsFactors = FALSE)
So, I am trying to create a graph between date(x-axis) and avg(y-axis). So this graph should change based on the selection from dropdown list of State.For example, for a particular selected state, it should show cities available(in other dropdown) in that state.
Below is my code:
library(shiny)
library(ggplot2)
library(plotly)
statelist<-as.list(data$state)
citylist<-as.list(data$city)
ui <- basicPage(
# plotOutput("plot1", click = "plot_click"),
# verbatimTextOutput("info")
sidebarPanel(
selectInput("plot1", label=h3("Select State"), choices = statelist),
selectInput("plot2", label=h3("Select City"), choices = citylist)
),
plotOutput(outputId="plot")
),
server <- function(input, output, session) {
observe(
{
state <- input$plot1
updateSelectInput(session, "plot2", choices = data$city[data$state == state])
}
),
output$plot<-renderPlot({
ggplot(data[data$city == input$plot2 &
data$state == input$plot1],aes(date,avg))
+geom_line()
})
}
shinyApp(ui, server)
Dropdown is working perfectly but not getting the graph.
Thanks in advance!!
I made some minor modifications to your code:
There were some commas in places where they should not be: after the ui constructor, and after the observe constructor.
There was a comma missing in data[data$city == input$plot2 &
data$state == input$plot1,]
I edited your observe to be an observeEvent
I modified the plot to show that it actually changes, since the sample data is quite limited.
Hope this helps!
library(shiny)
library(ggplot2)
library(plotly)
data<-data.frame(state=c('AZ','VA','CA','AZ','VA','CA'), city=c('Phoenix','Arlington','SantaClara','Mesa','Richmond','SF'),
avg=c(10,15,16,13,14,14), Date=c('01/09/2017','01/10/2017','01/11/2017','02/09/2017','02/10/2017','02/10/2017'),stringsAsFactors = FALSE)
statelist<-unique(data$state)
citylist<-unique(data$city)
ui <- basicPage(
# plotOutput("plot1", click = "plot_click"),
# verbatimTextOutput("info")
sidebarPanel(
selectInput("plot1", label=h3("Select State"), choices = statelist),
selectInput("plot2", label=h3("Select City"), choices = citylist)
),
plotOutput(outputId="plot")
)
server <- function(input, output, session) {
observeEvent(input$plot1,
{
state <- input$plot1
updateSelectInput(session, "plot2", choices = data$city[data$state == state])
}
)
output$plot<-renderPlot({
data = data[data$city == input$plot2 &
data$state == input$plot1,]
ggplot(data,aes(Date,avg)) + geom_point(size=5) + ggtitle(paste0(input$plot1," - ",input$plot2 ))
})
}
shinyApp(ui, server)
Related
I want to make an app with 2 actionButtons: 1) to submit the changes before loading a selectizeInput and 2) to draw the plot.
I know how to add a spinner after clicking a actionButton but the majority of the cases is added when you want to show the plot.
However, is it possible to add a spinner without showing any plot?
In this particular case, I want to show a spinner after clicking "Submit" until the selectizeInput from the 'Selection tab' is loaded. As you can see the example that I attach, it takes a bit to load all the choices (since the file has 25000 rows).
I already have one spinner after clicking the second actionButton (Show the plot) but I need one more.
I have created an example, but for some reason the plot is not shown in the shiny app and it appears in the window from R (I don't know why but I added the plot just to show you how I put the second spinner. I want a similar one but with the first actionButton.).
library(shiny)
library(shinycssloaders)
ui <- fluidPage(
titlePanel("My app"),
sidebarLayout(
sidebarPanel(
tabsetPanel(
tabPanel("Submit",
checkboxInput("log2", "Log2 transformation", value = FALSE),
actionButton("submit", "Submit")
),
tabPanel("Selection",
br(),
selectizeInput(inputId = "numbers", label = "Choose one number:", choices=character(0)),
actionButton("show_plot", "Show the plot")
))
),
mainPanel(
conditionalPanel(
condition = "input.show_plot > 0",
style = "display: none;",
withSpinner( plotOutput("hist"),
type = 5, color = "#0dc5c1", size = 1))
)
)
)
server <- function(input, output, session) {
data <- reactive({
data = read.csv("https://people.sc.fsu.edu/~jburkardt/data/csv/hw_25000.csv")
data[,1] <- as.character(data[,1])
if(input$log2 == TRUE){
cols <- sapply(data, is.numeric)
data[cols] <- lapply(data[cols], function(x) log2(x+1))
}
return(data)
})
mylist <- reactive({
req(data())
data <- data()
data <- data[,1]
return(data)
})
# This is to generate the choices (gene list) depending on the user's input.
observeEvent(input$submit, {
updateSelectizeInput(
session = session,
inputId = "numbers",
choices = mylist(), options=list(maxOptions = length(mylist()))
)
})
v <- reactiveValues()
observeEvent(input$show_plot, {
data <- data()
v$plot <- plot(x=data[,1], y=data[,2])
})
# If the user didn't choose to see the plot, it won't appear.
output$hist <- renderPlot({
req(data())
if (is.null(v$plot)) return()
if(input$show_plot > 0){
v$plot
}
})
}
Does anyone know how to help me, please?
Thanks very much
It's a little tricky.
First of all I'd update the selectizeInput on the server side as the warning suggests:
Warning: The select input "numbers" contains a large number of
options; consider using server-side selectize for massively improved
performance. See the Details section of the ?selectizeInput help
topic.
Furthermore I switched to ggplot2 regarding the plotOutput - Please see this related post.
To show the spinner while the selectizeInput is updating choices we'll need to know how long the update takes. This information can be gathered via shiny's JS events - please also see this article.
Finally, we can show the spinner for a non-existent output, so we are able to control for how long the spinner is shown (see uiOutput("dummyid")):
library(shiny)
library(shinycssloaders)
library(ggplot2)
ui <- fluidPage(
titlePanel("My app"),
tags$script(HTML(
"
$(document).on('shiny:inputchanged', function(event) {
if (event.target.id === 'numbers') {
Shiny.setInputValue('selectizeupdate', true, {priority: 'event'});
}
});
$(document).on('shiny:updateinput', function(event) {
if (event.target.id === 'numbers') {
Shiny.setInputValue('selectizeupdate', false, {priority: 'event'});
}
});
"
)),
sidebarLayout(
sidebarPanel(
tabsetPanel(
tabPanel("Submit",
checkboxInput("log2", "Log2 transformation", value = FALSE),
actionButton("submit", "Submit")
),
tabPanel("Selection",
br(),
selectizeInput(inputId = "numbers", label = "Choose one number:", choices=NULL),
actionButton("show_plot", "Show the plot")
))
),
mainPanel(
uiOutput("plotProxy")
)
)
)
server <- function(input, output, session) {
previousEvent <- reactiveVal(FALSE)
choicesReady <- reactiveVal(FALSE)
submittingData <- reactiveVal(FALSE)
observeEvent(input$selectizeupdate, {
if(previousEvent() && input$selectizeupdate){
choicesReady(TRUE)
submittingData(FALSE)
} else {
choicesReady(FALSE)
}
previousEvent(input$selectizeupdate)
})
data <- reactive({
data = read.csv("https://people.sc.fsu.edu/~jburkardt/data/csv/hw_25000.csv")
if(input$log2 == TRUE){
cols <- sapply(data, is.numeric)
data[cols] <- lapply(data[cols], function(x) log2(x+1))
}
return(data)
})
mylist <- reactive({
req(data()[,1])
})
observeEvent(input$submit, {
submittingData(TRUE)
reactivePlotObject(NULL) # reset
updateSelectizeInput(
session = session,
inputId = "numbers",
choices = mylist(), options=list(maxOptions = length(mylist())),
server = TRUE
)
})
reactivePlotObject <- reactiveVal(NULL)
observeEvent(input$show_plot, {
reactivePlotObject(ggplot(data(), aes_string(x = names(data())[1], y = names(data())[2])) + geom_point())
})
output$hist <- renderPlot({
reactivePlotObject()
})
output$plotProxy <- renderUI({
if(submittingData() && !choicesReady()){
withSpinner(uiOutput("dummyid"), type = 5, color = "#0dc5c1", size = 1)
} else {
conditionalPanel(condition = "input.show_plot > 0", withSpinner(plotOutput("hist"), type = 5, color = "#0dc5c1", size = 1), style = "display: none;")
}
})
}
shinyApp(ui, server)
First 100 rows of your example data (dput(head(data, 100)) - your link might be offline some day):
structure(list(Index = 1:100, Height.Inches. = c(65.78331, 71.51521,
69.39874, 68.2166, 67.78781, 68.69784, 69.80204, 70.01472, 67.90265,
66.78236, 66.48769, 67.62333, 68.30248, 67.11656, 68.27967, 71.0916,
66.461, 68.64927, 71.23033, 67.13118, 67.83379, 68.87881, 63.48115,
68.42187, 67.62804, 67.20864, 70.84235, 67.49434, 66.53401, 65.44098,
69.5233, 65.8132, 67.8163, 70.59505, 71.80484, 69.20613, 66.80368,
67.65893, 67.80701, 64.04535, 68.57463, 65.18357, 69.65814, 67.96731,
65.98088, 68.67249, 66.88088, 67.69868, 69.82117, 69.08817, 69.91479,
67.33182, 70.26939, 69.10344, 65.38356, 70.18447, 70.40617, 66.54376,
66.36418, 67.537, 66.50418, 68.99958, 68.30355, 67.01255, 70.80592,
68.21951, 69.05914, 67.73103, 67.21568, 67.36763, 65.27033, 70.84278,
69.92442, 64.28508, 68.2452, 66.35708, 68.36275, 65.4769, 69.71947,
67.72554, 68.63941, 66.78405, 70.05147, 66.27848, 69.20198, 69.13481,
67.36436, 70.09297, 70.1766, 68.22556, 68.12932, 70.24256, 71.48752,
69.20477, 70.06306, 70.55703, 66.28644, 63.42577, 66.76711, 68.88741
), Weight.Pounds. = c(112.9925, 136.4873, 153.0269, 142.3354,
144.2971, 123.3024, 141.4947, 136.4623, 112.3723, 120.6672, 127.4516,
114.143, 125.6107, 122.4618, 116.0866, 139.9975, 129.5023, 142.9733,
137.9025, 124.0449, 141.2807, 143.5392, 97.90191, 129.5027, 141.8501,
129.7244, 142.4235, 131.5502, 108.3324, 113.8922, 103.3016, 120.7536,
125.7886, 136.2225, 140.1015, 128.7487, 141.7994, 121.2319, 131.3478,
106.7115, 124.3598, 124.8591, 139.6711, 137.3696, 106.4499, 128.7639,
145.6837, 116.819, 143.6215, 134.9325, 147.0219, 126.3285, 125.4839,
115.7084, 123.4892, 147.8926, 155.8987, 128.0742, 119.3701, 133.8148,
128.7325, 137.5453, 129.7604, 128.824, 135.3165, 109.6113, 142.4684,
132.749, 103.5275, 124.7299, 129.3137, 134.0175, 140.3969, 102.8351,
128.5214, 120.2991, 138.6036, 132.9574, 115.6233, 122.524, 134.6254,
121.8986, 155.3767, 128.9418, 129.1013, 139.4733, 140.8901, 131.5916,
121.1232, 131.5127, 136.5479, 141.4896, 140.6104, 112.1413, 133.457,
131.8001, 120.0285, 123.0972, 128.1432, 115.4759)), row.names = c(NA,
100L), class = "data.frame")
I have two datasets, one with a list of two hundred cities and their corresponding state and another much larger dataset that I'd like to make an app to sort through. I need help making two drop down boxes in my shiny app where the first is the state variable and the second is the list of cities within that chosen state. I then want those selections to filter the much larger, second dataset in the output. I've tried solutions from several similar but slightly different examples online, but I'm having trouble translating it to what I'm doing.
So far I have this:
ui <- fluidPage(
headerPanel(''),
sidebarPanel(
#add selectinput boxs
htmlOutput("state_selector"),
htmlOutput("city_selector"),
),
mainPanel(
fluidRow(
# Create a new row for the table.
DT::dataTableOutput("table")
)
server <- function(session, input, output) {
output$state_selector = renderUI({
selectInput("state", label = h4("State"),
choices = as.character(unique(citystatedata$state)), selected = NULL)
})
output$city_selector = renderUI({
data_available = citystatedata[citystatedata$State == input$state, "state"]
selectInput(inputId = "city", #name of input
label = "City", #label displayed in ui
choices = unique(data_available), #calls list of available cities
selected = unique(data_available)[1])
})
shinyApp(ui = ui, server = server)
I tried to take out the portions of the code that weren't specifically related to the drop down boxes, since that's what I was more specifically asking about. So I'm sorry if I've left anything out! Let me know if I need to include anything else
Using available gapminder data, you can try this.
df <- gapminder
df$state <- gapminder$continent
df$city <- gapminder$country
citystatedata <- df
ui <- fluidPage(
headerPanel('Test'),
sidebarPanel(
#add selectinput boxs
uiOutput("state_selector"),
uiOutput("city_selector"),
),
mainPanel(
fluidRow(
# Create a new row for the table.
DTOutput("table")
)
)
)
server <- function(session, input, output) {
output$state_selector = renderUI({
selectInput("state", label = h4("State"),
choices = as.character(unique(citystatedata$state)), selected = NULL)
})
output$city_selector = renderUI({
data_available = citystatedata[citystatedata$state == req(input$state),]
selectInput(inputId = "city", #name of input
label = "City", #label displayed in ui
choices = unique(data_available$city), #calls list of available cities
selected = 1)
})
mydt <- reactive({
citystatedata %>% filter(citystatedata$state == req(input$state) & citystatedata$city %in% req(input$city))
})
output$table <- renderDT(mydt())
}
shinyApp(ui = ui, server = server)
I am building a shiny app that looks at our media sales.
My data is in a csv file
I want to be able to select any year and only have the row with the selected year be displayed.
As seen in the image.
Can someone help with the server out statement
media <- read.csv("media.csv",stringsAsFactors=FALSE)
State,Year,DVD,BluRay,Download
CT,2013,265,95,141
CT,2014,201,54,65
CT,2015,154,62,28
CT,2016,96,23,72
CT,2017,49,84,36
MA,2013,116,321,108
MA,2014,66,119,145
MA,2015,69,64,121
MA,2016,84,81,210
MA,2017,79,35,96
MD,2013,161,36,26
MD,2014,24,97,84
MD,2015,201,74,24
MD,2016,254,74,154
MD,2017,95,63,247
NJ,2013,78,60,168
NJ,2014,201,85,321
NJ,2015,209,75,245
NJ,2016,217,55,88
NJ,2017,65,46,71
PA,2013,94,95,68
PA,2014,232,91,94
PA,2015,154,73,203
PA,2016,87,101,119
PA,2017,200,98,149
Code:
library(shiny)
ui <- fluidPage(
titlePanel('DVD/BluRay/Download:'),
sidebarLayout(
sidebarPanel(
selectInput("State", label = h4("Which State are you in:"),choices =media$State),
checkboxGroupInput("Category", label = h4("Category"),
choices = list("DVD" , "BluRay" , "Download" ),
selected = list("DVD" , "BluRay" , "Download" )),
checkboxGroupInput("Year", label = h4("Which Year(s)"),choices = unique(media$Year))
),
mainPanel(
tableOutput("mediadata")
)
)
)
server <- function(input, output) {
output$mediadata <- renderTable({
statefilter <- subset(media, media$State == input$State)
statefilter[c('State', 'Year', input$Category)]
})
}
shinyApp(ui = ui, server = server)
This works now:
output$mediadata <- renderTable({
statefilter <- subset(media[media$State == input$State & media$Year %in% input$Year,])
statefilter[c('State', 'Year', input$Category)]
})
I'm a bit of an RShiny and R novice. I'm trying to program an RShiny application. It would initially graphs a scatterplot matrix using the first three variables of the dataset by default. The user could then choose their own variable selections from a complete list of variables. Once variables are chosen, the user would click and action button and the graph would be recomputed using the newly selected variables.
I'm using selectinput rather than checkboxinput to accommodate datasets with many variables. I'm using the iris dataset. The code below produces the initial graph and allows the user to select the variables. I just can't figure out how to make it recompute the matrix plot. How do I do this? Thanks!
library(shiny)
runApp(list(
ui = fluidPage(
cols = colnames(iris),
headerPanel('Grow Clusters'),
tabsetPanel(
tabPanel("Plot",
sidebarPanel(
# uiOutput("varselect"),
selectInput("choose_vars", "Select variables to plot",
choices=colnames(iris), selected=iris[1:3], multiple=T),
actionButton("submitButton", "Produce Matrix Plot!")
),
mainPanel(
plotOutput('pairsplot')
)
),
tabPanel("Summary")
,
tabPanel("Table")
)
),
server = function(input, output) {
selectedData <- reactive({
cols = colnames(iris)
selectInput("choose_vars", "Select variables to plot",
choices=cols, selected=cols[1:3], multiple=T)
})
output$pairsplot <- renderPlot({
pairs(iris[1:3], pch = 21)
})
output$varselect <- renderUI({
iris[input$choose_vars]
plotOutput("pairsplot")
})
}
)
)
I think what you are looking for is quo function as in the Chris Beely blog: https://chrisbeeley.net/?p=1116
If you want users to pass arguments and then turn that character vector into objects r can read you need to use quo(input$choose_vars) and then in the plot you need to add !! before that passing variable. Notice you need to load dplyr.
library(shiny)
library(dplyr)
runApp(list(
ui = fluidPage(
cols = colnames(iris),
headerPanel('Grow Clusters'),
tabsetPanel(
tabPanel("Plot",
sidebarPanel(
# uiOutput("varselect"),
selectInput("choose_vars", "Select variables to plot",
choices=colnames(iris), selected=iris[1:3], multiple=T),
actionButton("submitButton", "Produce Matrix Plot!")
),
mainPanel(
plotOutput('pairsplot')
)
),
tabPanel("Summary")
,
tabPanel("Table")
)
),
server = function(input, output) {
selectedData <- reactive({
cols <- colnames(iris)
selectInput("choose_vars", "Select variables to plot",
choices=cols, selected=cols[1:3], multiple=T)
})
output$pairsplot <- renderPlot({
if(is.null(input$choose_vars) || length(input$choose_vars)<2){
pairs(iris[1:3], pch = 21)
} else {
var <- quo(input$choose_vars)
pairs(iris %>% select(!!var), pch = 21)
}
})
output$varselect <- renderUI({
iris[input$choose_vars]
plotOutput("pairsplot")
})
}
)
)
Issues between inputs and plot output
Hi,
I'm testing out a basic ShinyApp where I can generate a plot of commercial services broken down by geography and service type.
The idea is I want the user to use three drop-down menu inputs, each dependent upon the previous selection, to subset the data, which then gets output in a ggplot.
However, I'm having issues connecting the inputs to the plot output (see below). The inputs are working fine and reactive when selected, but I can't work out how to link that to the plot, I get the feeling I'm not using the right data source (but have no idea how to ensure it is). Furthermore, I'm not familiar with how I would go about adding a third filter (for "service") seeing as I don't know how to link my data source in the first place.
Sorry this is probably simple, but some help would be really appreciated.
UI
#Data
Test <- dataframe(
Geography1 = c("Region","Local Authority","County"...),
Geography2 = c("North West","Aldershot","Cheshire"...),
Service = c("Shop","Cafe","Library"...),
Overall_rating = c("Awesome","Good","Fantatstic"...),
Locations = c(4000, 1300, 1700...)
)
#SHINY APP
ui <- fluidPage(
titlePanel("Tool"),
sidebarLayout(
sidebarPanel(
uiOutput("geography1"),
uiOutput("geography2"),
uiOutput("service")),
mainPanel(
plotOutput("plot", height = "400px"))
)
)
Server
server <- function(input, output) {
output$geography1 = renderUI({
selectInput(inputId = "geog1",
label = "Geography 1:",
choices = as.character(unique(Test$Geography1)),
selected = "Region")
})
output$geography2 = renderUI({
datasub <- Test[Test$Geography1 == input$geog1, "Name"]
selectInput(inputId = "geog2",
label = "Geography2:",
choices = unique(datasub),
selected = unique(datasub)[1])
})
output$service = renderUI({
datasub2 <- unique(datasub)
selectInput(inputId = "service",
label = "Service type:",
choices = unique(...),
selected = unique(...)[1])
})
output$plot = renderPlot({
ggplot(datasub2(),aes(x = Overall_rating, y = Locations, fill= Overall_rating))+
geom_bar(stat = "identity")
})
}
shinyApp(ui, server)
It's hard to tell how the provided data is supposed to be filtered in the app but this code will at least run and be interactive. Hopefully from there you can figure out how to adjust the dataset.
As BigDataScientist said one fault is that you're not using a reactive dataset.
#Data
Test <- data.frame(
Geography1 = c("Region","Local Authority","County"),
Geography2 = c("North West","Aldershot","Cheshire"),
Service = c("Shop","Cafe","Library"),
Overall_rating = c("Awesome","Good","Fantatstic"),
Locations = c(4000, 1300, 1700)
)
#SHINY APP
ui <- fluidPage(
titlePanel("Tool"),
sidebarLayout(
sidebarPanel(
uiOutput("geography1"),
uiOutput("geography2"),
uiOutput("service")),
mainPanel(
plotOutput("plot", height = "400px"))
)
)
server <- function(input, output) {
output$geography1 = renderUI({
selectInput(inputId = "geog1",
label = "Geography 1:",
choices = as.character(unique(Test$Geography1)),
selected = "Region")
})
datasub <- reactive({
Test[Test$Geography1 == input$geog1,]
})
output$geography2 = renderUI({
selectInput(inputId = "geog2",
label = "Geography2:",
choices = unique(datasub()[,"Geography2"]),
selected = unique(datasub()[,"Geography2"])[1])
})
datasub2 <- reactive({
datasub()[Test$Geography2 == input$geog2, ]
})
output$service = renderUI({
selectInput(inputId = "service",
label = "Service type:",
choices = unique(datasub2()[,"Service"]),
selected = unique(datasub2()[,"Service"])[1])
})
datasub3 <- reactive({
datasub()[Test$Service == input$service, ]
})
output$plot = renderPlot({
ggplot(datasub3(),aes(x = Overall_rating, y = Locations, fill= Overall_rating))+
geom_bar(stat = "identity")
})
}
shinyApp(ui, server)