shiny conditionalPanel update problems - r

I have a Shiny app that doesn't give any error but clearly my conditionalPanel are not working properly. When I select the inputs some graphs get updated and some don't. For example if I select week and change the condition for 0 or 1 the graphs get updated, but if I select rel the graph gets update for 1 but not for 4 (If I do this outside the Shiny app it works for all cases). This is how the code looks like:
UI.R
shinyUI(pageWithSidebar(
headerPanel(' '),
sidebarPanel(
selectInput('zcol', 'Variable to be fixed', names(taxi[,-c(1,4,5,7,8,9,10,11)])),
conditionalPanel(condition = "input.zcol == 'week'",
selectInput("levels", "Levels",c(0,1)
)),
conditionalPanel(condition = "input.zcol == 'tollfree'",
selectInput("levels", "Levels",c(0,1)
)),
conditionalPanel(condition = "input.zcol == 'rel'",
selectInput("levels", "Levels",c(1,4)
)),
conditionalPanel(condition = "input.zcol == 'source'",
selectInput("levels", "Levels",c(1,2)
)),
conditionalPanel(condition = "input.zcol == 'hour'",
selectInput("levels", "Levels",c(seq(0,23))
))
),
mainPanel(
plotOutput('plot1'),
plotOutput('plot2')
)
))
Server.R
shinyServer(function(input, output, session) {
simiData <- reactive({
eval(substitute(taxi %>% group_by(simi.mean,col) %>% summarise(mean = mean(prop.conv)) %>%
filter(col==input$levels) %>% select(simi.mean,mean),
list(col=as.symbol(input$zcol))))
})
distData <- reactive({
eval(substitute(taxi %>% group_by(dist.mean,col) %>% summarise(mean = mean(prop.conv)) %>%
filter(col==input$levels) %>% select(dist.mean,mean),
list(col=as.symbol(input$zcol))))
})
output$plot1 <- renderPlot({
plot(simiData(),xlim=c(0,max(simiData()$simi.mean)),ylim=c(0,max(simiData()$mean)))
})
output$plot2 <- renderPlot({
plot(distData())
})
})
Any suggestions?
Thanks!

Instead of having multiple selectinputs, you can just have one and update the choices using updateSelectInput(session,"levels",choices = newValue)) You can use an observer to change the choices of input$levels each time a input$zcol changed.
Here is basic example of how to update a selectinput using an observer
taxi <- data.frame(week=sample(1:10),hour=sample(1:10))
runApp(list(
ui = shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("zcol", 'Variable to be fixed', names(taxi)),
selectInput("levels", "Levels",1:5)
),
mainPanel(
plotOutput('plot1')
)
)
)
),
server = function(input, output, session) {
output$plot1 <- renderPlot({
plot(taxi[1:input$levels,])
})
observe({
if ( input$zcol == 'week') {
updateSelectInput(session, "levels", choices = 1:5)
} else if(input$zcol == 'hour') {
updateSelectInput(session, "levels", choices = 6:10)
}
})
}
))

You can't have multiple selectInputs with the same inputId ("levels"). Each one needs a unique inputId.

Related

How to make this R Shiny table example reactive?

I found the following code that creates an RShiny app that allows users to visualize a data table based on certain columns that they select. See following code (should run on it's own):
library(shiny)
library(ggplot2) # for the diamonds dataset
ui <- fluidPage(
title = "Examples of DataTables",
sidebarLayout(
sidebarPanel(
conditionalPanel(
'input.dataset === "diamonds"',
checkboxGroupInput("show_vars", "Columns in diamonds to show:",
names(diamonds), selected = names(diamonds))
)
),
mainPanel(
tabsetPanel(
id = 'dataset',
tabPanel("diamonds", DT::dataTableOutput("mytable1")),
)
)
)
)
server <- function(input, output) {
# choose columns to display
diamonds2 = diamonds[sample(nrow(diamonds), 1000), ]
output$mytable1 <- DT::renderDataTable({
DT::datatable(diamonds2[, input$show_vars, drop = FALSE])
})
}
shinyApp(ui, server)
My question is, how can I change this dataset to be reactive, such that instead of always using the diamonds dataset, a data table would result based on what dataset I select from a dropdown menu? Such as adding a selectInput() argument?
If you are just trying to have different tables show based on a selectInput(), then this will work for a small number of tables. Essentially, the output table is an if else statement, which displays a different table depending on what's selected in the selectInput().
library(shiny)
library(ggplot2) # for the diamonds dataset
ui <- fluidPage(
title = "Examples of DataTables",
sidebarLayout(
sidebarPanel(
selectInput("Datasetchoice", "Dataset", choices = c("diamonds", "iris", "mtcars")), #Choose which dataset to display
conditionalPanel(
'input.dataset === "diamonds"',
checkboxGroupInput("show_vars", "Columns in diamonds to show:",
names(diamonds), selected = names(diamonds))
)
),
mainPanel(
tabsetPanel(
id = 'dataset',
tabPanel("diamonds", DT::dataTableOutput("mytable1"))
)
)
)
)
server <- function(input, output) {
# choose columns to display
diamonds2 = diamonds[sample(nrow(diamonds), 1000), ]
output$mytable1 <- DT::renderDataTable({
if(input$Datasetchoice == "diamonds") { #If else statement, show a different table depending on the choice
DT::datatable(diamonds2[, input$show_vars, drop = FALSE])
} else if (input$Datasetchoice == "iris") {
DT::datatable(iris)
} else if(input$Datasetchoice == "mtcars") {
DT::datatable(mtcars)
}
})
}
shinyApp(ui, server)
Here is a solution that updates the checkboxes and the table upon selection of a different dataset. No limit on the number of datasets. But the datasets must be dataframes.
library(shiny)
library(datasets) # for the datasets
ui <- fluidPage(
title = "Examples of DataTables",
sidebarLayout(
sidebarPanel(
selectInput("dat",
label = "Choose data",
choices = c("cars", "mtcars", "faithful", "iris", "esoph", "USArrests")),
checkboxGroupInput("datavars", "Columns to show",
choices = NULL,
selected = NULL)
),
mainPanel(
tabsetPanel(
id = 'dataset',
tabPanel("dataset", DT::dataTableOutput("mytable1")),
)
)
)
)
server <- function(input, output, session) {
r <- reactiveValues(
dataobj = NULL
)
observeEvent(input$dat, {
dataobj <- r$dataobj <- get(input$dat, 'package:datasets')
datavars <- names(dataobj)
freezeReactiveValue(input, "datavars")
updateCheckboxGroupInput(session, "datavars",
choices = datavars,
selected = datavars)
})
output$mytable1 <- DT::renderDataTable({
req(r$dataobj, input$datavars)
DT::datatable(r$dataobj[, input$datavars, drop = FALSE])
})
}
shinyApp(ui, server)

R Shiny: How to Displayed values in filter with ascending Order

How to Displayed values in filter with ascending Order.
Want to displayed filter of week in dataTableOutput with value in ascending order.
Here is the code of ui.R
fluidPage(
titlePanel("Delivery Assurance Matrix"),
fluidRow(
column(4,
selectInput("week_count",
"Week",
c("All",
sort(unique(as.character(data$Week))))
))),
DT::dataTableOutput("table")
)
Here is the code of server.R
function(input, output) {
output$table <- DT::renderDataTable(DT::datatable({
data<-data
if (input$week_count != "All") {
data <- data[data$Week >= input$week_count,]
}
data
}))
}
But in UI Values not in ordering
You can also you shinyWidgets package which has Select All Option
library(shiny)
library(shinyWidgets)
data <- c(11,1,2,3,10,21)
ui <- fluidPage(
titlePanel("Delivery Assurance Matrix"),
fluidRow(
column(4,
pickerInput(
inputId = "week_count",
label = "Week",
choices = sort(data),
multiple = TRUE,
options = list(
`actions-box` = TRUE,
`deselect-all-text` = "None...",
`select-all-text` = "Select All",
`none-selected-text` = "None Selected"
)
)
)),
DT::dataTableOutput("table")
)
server <- function(input, output) {}
shinyApp(ui = ui, server = server)
Its solved by this changes.
fluidRow(
column(4,
selectInput("week_count",
"Week",
c("All",
order(sort(unique(as.character(data$Week)))))
))

Tabs with different sidebars

I am trying to create a shiny app with multiple tabs. Each tab is to have its own sidebar. I haven't been able to get this to work. Any help on what is wrong would be appreciated.
Below is the code
ui <- fluidPage(
titlePanel("Hi"),
sidebarLayout(position = "left",
sidebarPanel(
conditionalPanel(condition = "input.tabs1==1",
selectizeInput('invar',"Reg in", choices = varnames, multiple = TRUE)),
conditionalPanel(condition = "input.tabs1==2",
selectizeInput('outvar',"Reg out", choices = predictors, multiple = FALSE)),
),
mainPanel(
tabsetPanel(id="tabs1",
tabPanel("input",value=1,plotOutput("Input"),
tabPanel("output",value=2,plotOutput("Output")
))))
))
First of all, check your code again. You made following mistakes:
one tabPanel is nested inside the other one
there's an extra comma at the end of the second conditionalPanel(), so you pass an empty element to sidebarPanel()
If I correct your mistakes and create a mock example, it works perfectly fine as is. So there isn't really a problem here:
ui <- fluidPage(
titlePanel("Hi"),
sidebarLayout(position = "left",
sidebarPanel(
conditionalPanel(condition = "input.tabs1==1",
selectizeInput('invar',"Reg in", choices = letters[1:3], multiple = TRUE)),
conditionalPanel(condition = "input.tabs1==2",
selectizeInput('outvar',"Reg out", choices = letters[4:6], multiple = FALSE))
),
mainPanel(
tabsetPanel(id="tabs1",
tabPanel("input",value=1,plotOutput("Input")),
tabPanel("output",value=2,plotOutput("Output"))
)
)
))
server <- function(input, output, session){
output$Input <- renderPlot(plot(1))
output$Output <- renderPlot(plot(2))
}
shinyApp(ui, server)
You could do this as well by using renderUI:
ui <- fluidPage(
titlePanel("Hi"),
sidebarLayout(position = "left",
sidebarPanel(
uiOutput("mysidebar")
),
mainPanel(
tabsetPanel(id="tabs1",
tabPanel("input",value=1,plotOutput("Input")),
tabPanel("output",value=2,plotOutput("Output")
)))
))
server <- function(input, output, session){
output$mysidebar <- renderUI({
if(input$tabs1 == 1){
selectizeInput('invar',"Reg in", choices = letters[1:3])
} else if(input$tabs1 == 2){
selectizeInput('outvar',"Reg out", choices = letters[4:6])
}
})
}
shinyApp(ui,server)
I do this in a very different but effective way.
shinyApp(
shinyUI(
fluidPage(
uiOutput('mainpage')
)
),
shinyServer(function(input, output, session) {
panel <- reactiveValues(side = NULL)
output$mainpage <- renderUI({
sidebarLayout(position = "left",
sidebarPanel(
uiOutput(panel$side)
),
mainPanel(
tabsetPanel(id="tabs1",
tabPanel("input",value=1,plotOutput("Input")),
tabPanel("output",value=2,plotOutput("Output"))
)
)
})
output$sideinput <- renderUI({
tagList(
selectizeInput('invar',"Reg in", choices = varnames, multiple = TRUE))
)
})
output$sideoutput <- renderUI({
tagList(
selectizeInput('outvar',"Reg out", choices = predictors, multiple =FALSE)
)
})
observeEvent(input$tabs1,{
panel$side <- switch(input$tabs1,
1 = 'sideinput',
2 = 'sideoutput')
})
basically I am using observers as my conditionals and assigning the value of the desired panel to the variable name assigned to that panel position

Shiny selectizeInput: on click remove the initial selected value

i would like to remove the initial value (selected=) from selectizeInput when the user click on the widget.
Here is a sample code:
library(shiny)
library(dplyr)
ui= fluidPage(
sidebarLayout(
sidebarPanel(
selectizeInput(inputId= "cyl", label= "cyl",
choices= NULL,
selected= sort(unique(mtcars$cyl))[1],
multiple=T)
),
mainPanel(
tableOutput("tab")
)
)
)
server= function(input, output,session) {
updateSelectizeInput(session = session,inputId ="cyl",choices=sort(unique(mtcars$cyl)),selected=sort(unique(mtcars$cyl))[1], server = TRUE)
df_filtered= reactive({
mtcars %>%
{if (is.null(input$cyl)) . else filter(., cyl %in% input$cyl)}
})
output$tab= renderTable(df_filtered())
}
shinyApp(ui, server)
Just a bit of explanation on base of sample code:
The initial selected value in selectizeInput "cyl" is 4. When the user press on this widget, i would like that the value 4 is removed and the selected option is cleared. Any ideas?
*I have used the function updateSelectizeInput in server because in my shiny app choice selection is very big leading to too long loading time
You can use shinyjs::onclick to call updateSelectizeInput when the user clicks on the selectize field, eg:
library(shiny)
library(dplyr)
library(shinyjs)
ui= fluidPage(
useShinyjs(),
sidebarLayout(
sidebarPanel(
selectizeInput(inputId= "cyl", label= "cyl",
choices= NULL,
selected= sort(unique(mtcars$cyl))[1],
multiple=T)
),
mainPanel(
tableOutput("tab")
)
)
)
server= function(input, output,session) {
updateSelectizeInput(session = session,inputId ="cyl",choices=sort(unique(mtcars$cyl)),selected=sort(unique(mtcars$cyl))[1], server = TRUE)
df_filtered= reactive({
mtcars %>%
{if (is.null(input$cyl)) . else filter(., cyl %in% input$cyl)}
})
output$tab= renderTable(df_filtered())
onclick("cyl", {
updateSelectizeInput(session, "cyl", selected = "")
})
}
shinyApp(ui, server)

Shiny App checkboxInput and conditionalPanel

I am new to ShinyApp.
I want to use a checkboxInput() with conditionalPanel, so when it's checked, the options for Type will show up (then users can select a Type from "BEER", "REFRESHMENT", "SPIRITS", "WINE"). If it's not checked, the options for Type will not show up.
Below are my code, but when the Type options didn't show no matter I check the box or not. I guess I should write something in the server function? I really don't know. Thank you for your help.
ui <- fluidPage(
titlePanel("BC Liquor Store prices"),
img(src = "BCLS.png",align = "right"),
sidebarLayout(
sidebarPanel(sliderInput("priceInput", "Price", 0, 100, c(25, 40), pre = "$"),
wellPanel(
checkboxInput("checkbox", "Filter by Type", FALSE),
conditionalPanel(
condition="checkbox==true",
selectInput("typeInput", "Product type",
choices = c("BEER", "REFRESHMENT", "SPIRITS", "WINE"),
selected = "WINE")
)
),
uiOutput("countryOutput")
),
mainPanel(
tabsetPanel(
tabPanel("Plot", plotOutput("coolplot")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("results"))
)
)
)
)
server <- function(input, output, session) {
output$countryOutput <- renderUI({
selectInput("countryInput", "Country",
sort(unique(bcl$Country)),
selected = "CANADA")
})
filtered <- reactive({
if (is.null(input$countryInput)) {
return(NULL)
}
bcl %>%
filter(Price >= input$priceInput[1],
Price <= input$priceInput[2],
Type == input$typeInput,
Country == input$countryInput
)
})
output$coolplot <- renderPlot({
if (is.null(filtered())) {
return()
}
filtered() %>% ggvis(~Alcohol_Content, fill := "#fff8dc") %>%
layer_histograms(width = 1, center = 0)
})
output$results <- renderTable({
filtered()
})
}
I came across this question recently while researching a similar one.
It seems the simple answer to the checkboxInput condition is as below:
condition="input.checkbox==1",
OK, you can classify conditional inputs in two categories.
1) Inputs that depend on the ui.R (in your case the checkboxInput)
2) Inputs that depend on the server.R (not necessary in your example)
Solutions:
1) you can easily solve with a renderUI() function, see the example below.
If you really want 2), you would need a conditionalPanel and you would use a reactive function in the server.R, that you save in an output object and access it with small JS-snippet in the ui.R. For me it looks like 1) is enough for you, if I am mistaken, let me know then we adapt the answer to solve 2).
A hint:
As a default your "checkbox" input takes the boolean value: false. So you would not render the "typeInput" (until you click "checkbox"). So up to that point "typeInput" is null.
However, if you now make dependencies on "typeInput" shiny will be confused,
since "typeInput" is not rendered and therefore does not exist.
So before using "typeInput", you should check, whether it is available:
if(!is.null(input$typeInput)) otherwise shiny will complain that you actually do not have a "typeinput" in your app (again: at least until you click "checkbox").
ui <- fluidPage(
titlePanel("BC Liquor Store prices"),
img(src = "BCLS.png",align = "right"),
sidebarLayout(
sidebarPanel(sliderInput("priceInput", "Price", 0, 100, c(25, 40), pre = "$"),
wellPanel(
checkboxInput("checkbox", "Filter by Type", FALSE),
uiOutput("conditionalInput")
),
uiOutput("countryOutput")
),
mainPanel(
tabsetPanel(
tabPanel("Plot", plotOutput("coolplot")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("results"))
)
)
)
)
server <- function(input, output, session) {
output$countryOutput <- renderUI({
selectInput("countryInput", "Country",
sort(unique(bcl$Country)),
selected = "CANADA")
})
output$conditionalInput <- renderUI({
if(input$checkbox){
selectInput("typeInput", "Product type",
choices = c("BEER", "REFRESHMENT", "SPIRITS", "WINE"),
selected = "WINE")
}
})
filtered <- reactive({
if (is.null(input$countryInput)) {
return(NULL)
}
bcl %>%
filter(Price >= input$priceInput[1],
Price <= input$priceInput[2],
Type == input$typeInput,
Country == input$countryInput
)
})
output$coolplot <- renderPlot({
if (is.null(filtered())) {
return()
}
filtered() %>% ggvis(~Alcohol_Content, fill := "#fff8dc") %>%
layer_histograms(width = 1, center = 0)
})
output$results <- renderTable({
filtered()
})
}
# run the app
shinyApp(ui = ui, server = server)

Resources