Same inputid in 2 conditionalPanel - Shiny - r

I'm a Shiny newbie and was trying to get something simple working, but unable to :(
Here is a part of my ui.R
sidebarLayout(
sidebarPanel(
radioButtons("market",
"Choose a Region to build the Sales file:",
c("North America & ANZ" = "NA", "Europe" = "EU"), inline = TRUE),
conditionalPanel(
condition = "input.market == 'NA'",
radioButtons("Locale",
"Choose a locale to see the sales Calendar:",
c("US and Canada" = "US_CA", "ANZ" = "ANZ"), inline = TRUE),
numericInput("sale_num", "Choose a Sale Number from the Table below",1,width = '100px' )
),
conditionalPanel(
condition = "input.market == 'EU'",
radioButtons("Locale",
"Choose a locale to see the sales Calendar:",
c("UK" = "UK", "FR and RoE" = "FR_ROE","DE,AT & CH" = "DACH"), inline = TRUE),
numericInput("sale_num", "Choose a Sale Number from the Table below",1,width = '100px' )),
dataTableOutput("sales"))
),
Here is my server.R
server <- shinyServer(function(input, output) {
output$sales <- renderDataTable({
saleTable(input$Locale)
},options = list(autoWidth = FALSE,searching = FALSE,pageLength=10))
})
When a change in the market radio button is triggered, the Locale radio does not update and hence the sales output table still has stale values and is not reflected by any change in Locale values.
I know I'm supposed to use something like UpdateRadiobuttons, but I'm not sure how. :(
saleTable is just a function in my Rscript that produces a data table.
Please help!
Thanks in advance!

Please post a minimal example, i.e. your function saleTable. Don't use the same input ID twice in your app, it's bad style and will not work in most cases. Here are two solutions: First one is bad style, second one better style.
1) Rename the second Locale to Locale2 and put this in your output$sales:
output$sales <- renderDataTable({
if(input$market == 'NA') data <- input$Locale
else if(input$market=="EU") data <- input$Locale2
saleTable(data)
}, options = list(autoWidth = FALSE,searching = FALSE,pageLength=10))
)
2) Create the second output as UIOutput and make it dependent on the first one:
ui <- shinyUI(
sidebarLayout(
sidebarPanel(
radioButtons("market",
"Choose a Region to build the Sales file:",
c("North America & ANZ" = "NA", "Europe" = "EU"), inline = TRUE),
uiOutput("Locale")),
mainPanel(dataTableOutput("sales"))))
server <- function(input, output, session) {
output$Locale <- renderUI({
if(input$market == "NA") myChoices <- c("US and Canada" = "US_CA", "ANZ" = "ANZ")
else myChoices <- c("UK" = "UK", "FR and RoE" = "FR_ROE","DE,AT & CH" = "DACH")
radioButtons("Locale","Choose a locale to see the sales Calendar:",
choices <- myChoices,
inline = TRUE)
})
output$sales <- renderDataTable({
saleTable(input$Locale)
},options = list(autoWidth = FALSE,searching = FALSE,pageLength=10))
}
shinyApp(ui = ui, server = server)

Based on the expressed interest in using updateRadioButtons, I put together a simple example with two radio buttons and a table output.
The first radio button input does not change. The second radio button input depends on the value of the first input. The table displayed is the mtcars data frame filtered by the values of the two radio button groups.
Using observeEvent ensures the value of the carb radio input updates each time the cyl radio input is changed. This will also trigger when the application is first launched and is why we do not see the default, dummy, choice "will be replaced" for the carb radio input.
Make sure to include session as one of the Shiny server function arguments. All of Shiny's update*Input functions require you pass a session object to them.
I hope this proves useful.
library(shiny)
shinyApp(
ui = fluidPage(
fluidRow(
column(
width = 4,
radioButtons(
inputId = "cyl",
label = "Choose number of cylinders:",
choices = unique(mtcars$cyl),
selected = unique(mtcars$cyl)[1]
),
radioButtons(
inputId = "carb",
label = "Choose number of carburetors:",
choices = "will be replaced"
)
),
column(
width = 8,
tableOutput(
outputId = "mtcars"
)
)
)
),
server = function(input, output, session) {
observeEvent(input$cyl, {
newChoices <- sort(unique(mtcars[mtcars$cyl == input$cyl, ]$carb))
updateRadioButtons(
session = session,
inputId = "carb",
choices = newChoices,
selected = newChoices[1]
)
})
output$mtcars <- renderTable({
req(input$cyl, input$carb)
mtcars[mtcars$cyl == input$cyl & mtcars$carb == input$carb, ]
})
}
)

Related

Shiny, reuss reactive input pickerInput

I am trying to create my first shiny app but I am facing a difficulty: in the reproducible example below I am creating a reactive pickerInput (i.e. only show brands proposing a cylindre equal to the input visitors select).
I then want that based on the combination input_cyl and picker_cny (remember that picker_cny depends on input_cyl) to display a table which shows the relevant data for the observation matching the combination input_cyl and picker_cny.
Thank you for your help!
df <- mtcars
df$brand <- rownames(mtcars)
df$brand <- gsub("([A-Za-z]+).*", "\\1", df$brand)
if (interactive()) {
library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinycssloaders)
# Define UI -----------------------------------------------
ui <- fluidPage(
# Application title
titlePanel("Reproducible Example"),
# Parameters
sidebarLayout(
sidebarPanel(
selectInput(inputId = "input_cyl", label = "Cyl",
choices = c("6", "4", "8")),
pickerInput(
inputId = "picker_cny",
label = "Select Company",
choices = paste0(unique(df$brand)),
options = list(`actions-box` = TRUE),
multiple = TRUE),
width = 2),
# Show Text
mainPanel(
tableOutput("table"),
width = 10)
))
# Define Server ------------------------------------------
server <- function(input, output, session) {
# Reactive pickerInput ---------------------------------
observeEvent(input$input_cyl, {
df_mod <- df[df$cyl == paste0(input$input_cyl), ]
# Method 1
disabled_choices <- !df$cyl %in% df_mod$cyl
updatePickerInput(session = session,
inputId = "picker_cny",
choices = paste0(unique(df$brand)),
choicesOpt = list(
disabled = disabled_choices,
style = ifelse(disabled_choices,
yes = "color: rgba(119, 119, 119, 0.5);",
no = "")
))
}, ignoreInit = TRUE)
output$table <- renderTable(df)
}
}
# Run the application
shinyApp(ui = ui, server = server)
You need a reactive that will handle the change in the input and subset the dataframe before giving it to the output table. For that, you just need to add this block to your server:
data <- reactive({
if (length(input$picker_cny) > 0)
df[df$brand %in% input$picker_cny,]
else
df
})
and update the output$table like this:
output$table <- renderTable(data())
Note: feel free to remove the if else in the reactive to get that:
data <- reactive({
df[df$brand %in% input$picker_cny,]
})
The only difference in that case is: would you show all or nothing when no input has been entered yet. That's a matter of taste.

Why do my observeEvent() calls in R Shiny not do anything once they have reactive expressions inside of them?

I am building a Shiny App where users can filter out certain projects. I want the project names to appear in the dropdown only if they appear within a certain date range.
I've been able to populate the selectize menu and have been able to make it so users can select all or remove all projects (from the answer to a question I asked previously). However, now that I'm trying to make these names reactive to the date, the observeEvent code from my previous question crashes. I tried to wrap it in a reactive expression, but then nothing happens.
How do I make my projects filterable by date while still keeping the select all and remove all functionality?
library(shiny)
library(plotly)
library(shinyjs)
library(shinydashboard)
library(shinyWidgets)
library(dplyr)
library(htmltools)
library(lubridate)
ui = fluidPage(
tabsetPanel(
tabPanel("View 1", fluid = TRUE,
sidebarLayout(
sidebarPanel(
h4("Select Your Desired Filters"),
div(id = "inputs",
dateRangeInput(
inputId = "date_filter",
label = "Filter by Month and Year",
start = today(),
end = (today() + 90),
min = "2021-04",
max = NULL,
format = "yyyy-mm",
startview = "month",
weekstart = 0,
language = "en",
separator = " to ",
width = NULL,
autoclose = TRUE
),
br()),
h5("Include/Exclude Specific Projects"),
selectizeInput(inputId = "filter_by_project",
label = "Filter by Project",
choices = sort(unique(test$project)),
multiple = TRUE,
selected = sort(unique(test$project))),
actionButton(inputId = "remove_all",
label = "Unselect All Projects", style = "color: #FFFFFF; background-color: #CA001B; border_color: #CA001B"),
actionButton(inputId = "add_all",
label = "Select All Projects", style = "color: #FFFFFF; background-color: #CA001B; border_color: #CA001B")
),
mainPanel(
)
)
)
)
)
server = function(input, output, session) {
#Here's the dataset
test <- tibble(project = c("Justin", "Corey","Sibley"),
date = ymd(c("2021-04-20", "2021-04-01", "2021-05-05")),
april_2021 = c(10, 100, 101),
may_2021 = c(1, 4, 7))
#I want users to be able to filter the list of projects by date, which should update the selectize options
test <- reactive({
test %>%
dplyr::filter(date >= input$date_filter[1],
date <= input$date_filter[2])
})
observeEvent(input$remove_all, {reactive({
updateSelectizeInput(session,"filter_by_project",choices=sort(unique(test()$project)),
selected=NULL, options = list(placeholder="Please Select at Least One Project")
)
})
})
observeEvent(input$add_all, {reactive({
updateSelectizeInput(session,"filter_by_project",choices=sort(unique(test()$project)), selected=sort(unique(test()$project)) )
})
})
}
shinyApp(ui = ui, server = server)
You have to major problems. First is using the same name for your input data.frame and for your reactive element. You've called them both test which causes confusion as to whether you are trying to use the data.frame or the reactive object. You should use different names. The second problem is you do not need to use reactive() for your observeEvents() calls. You just need to put the code you want to run in a block.
Fixing these problems, your server functon should look more like this
server = function(input, output, session) {
#Here's the dataset
testdata <- tibble(project = c("Justin", "Corey","Sibley"),
date = ymd(c("2021-04-20", "2021-04-01", "2021-05-05")),
april_2021 = c(10, 100, 101),
may_2021 = c(1, 4, 7))
#I want users to be able to filter the list of projects by date, which should update the selectize options
test <- reactive({
testdata %>%
dplyr::filter(date >= input$date_filter[1],
date <= input$date_filter[2])
})
observeEvent(input$remove_all, {
updateSelectizeInput(session,"filter_by_project", choices=sort(unique(test()$project)),
selected=NULL, options = list(placeholder="Please Select at Least One Project")
)
})
observeEvent(input$add_all, {
updateSelectizeInput(session,"filter_by_project", choices=sort(unique(test()$project)), selected=sort(unique(test()$project)) )
})
}

Need help making dependent dropdown boxes in the RStudio package Shiny

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)

checkboxGroupInput displaying list of table elements rather than table itself

I am creating an R Shiny application primarily using checkboxGroupInput where for each checkbox name I check, the corresponding table should display in the main UI panel. I have linked each checkbox option to its corresponding table (already in my previous script) in the "choices" argument of checkboxGroupInput. I use eventReactive to make a working button and renderTable to produce the appropriate tables. However, what displays in the main panel when I click the button is a list of each cell in the table rather than the table itself. This list of values looks a bit like this:
list(CUI = "C05372341", LAT = "ENG", TS = "P", LUI = "L0883457", STT = "PF", SUI = "S13423408", ISPREF = "N", AUI = "A10344304", SAUI = "21823712", SCUI = "1341953", SDUI = NA, SAB = "LKDHDS", TTY = "IN", CODE = "139433", STR = "Pramlintide", SRL = "0", SUPPRESS = "Y", CVF = "4354")
I would like this to have been printed in table form.
When I simply use renderTable({table_name}) on any given one of the tables, the table prints in the main panel how I would like it to. However, when I use eventReactive, name that variable, and renderTable on that variable, that is when the list of table values prints instead. Any ideas?
library(shiny)
ui <- fluidPage(
titlePanel("RxNorm Diabetic Drug Mapping based on Epocrates Classes"),
sidebarLayout(
sidebarPanel(
checkboxGroupInput("drugs", "Drug Class", choices = list("ALPHA GLUCOSIDASE INHIBITORS" = agi, "AMYLIN MIMETICS" = pramlintide, "BIGUANIDES" = biguanides, "DOPAMINE AGONISTS" = bromocriptine, "DPP4 INHIBITORS" = dpp4, "GLP1 AGONISTS" = glp1, "INSULINS" = insulins, "MEGLITINIDES" = meglitinides, "SGLT2 INHIBITORS" = sglt2, "SULFONYLUREAS" = sulfonylureas, "THIAZOLIDINEDIONES" = thiazolidinediones)),
actionButton("button", "Retrieve Data")
),
mainPanel(
tableOutput("results")
)
)
)
server <- function(input, output) {
table_reactive <- eventReactive(input$button, {
input$drugs
})
output$results <- renderTable({
table_reactive()
})
}
shinyApp(ui = ui, server = server)
In your choices:
choices = list("ALPHA GLUCOSIDASE INHIBITORS" = agi, "AMYLIN MIMETICS" = pramlintide ...), it's not valid if agi and pramlintide ... are pointing to tables. choices values can only be string.
You shouldn't pass variable as values in checkboxGroupInput. Instead you should pass the table name as string.
To answer your questions:
Please see the demos below:
If your tables are saved as separate variables, you should use sym() and eval_tidy() in rlang package to convert string to varaible.
library(shiny)
library(rlang)
ui <- fluidPage(
fluidRow(
checkboxGroupInput(
inputId = "checkgroup",
label = "Select Table",
choices = list(iris = "iris", mtcars = "mtcars")
),
actionButton(
inputId = "confirm",
label = "Confirm Table(s)"
)
),
fluidRow(
tags$div(id = "tables")
)
)
server <- function(input, output, session) {
observeEvent(input$confirm,{
removeUI(selector = "#tables > *",multiple = TRUE)
req(length(input$checkgroup) > 0)
for(table_name in input$checkgroup){
table_id <- paste0("mytable",table_name)
insertUI(
selector = "#tables",
ui = dataTableOutput(table_id)
)
output[[table_id]] <- renderDataTable(eval_tidy(sym(table_name)))
}
})
}
shinyApp(ui, server)

R shiny: multiple select choices. selectize and dropdownbutton setting, when multiple choices made, aggregate data collapsed

Hi I'm using both selectize and dropdownbuttons to build multiple choices select widget for my user. It works fine when single choice is made, however when you make multiple choices, the aggregate data showed is incorrect.
Here is my code:
ui:
library(shiny)
shinyUI(fluidPage(
dropdownButton(
label = "Country", status = "default", width = 400,
checkboxGroupInput(inputId = "var", label = "Country",
choices = c("ALL", "Null", "A2", "AE", "AF"),
selected = c("ALL") )
),
hr(),
dropdownButton(
label = "Platform ", status = "default", width = 400,
checkboxGroupInput(inputId = "plat", label = "Platform ",
choices = c("ALL", "Android","Ios"),
selected = c("Android"))
),
hr(),
selectizeInput(inputId ='media',
label = "Source",
choices = c("ALL", "facebook", "twitter"),
selected = c("ALL"),
multiple = T),
),
mainPanel(
textOutput("text1")
)
))
server:
#server.R
library(shiny)
library(ggplot2)
library(dplyr)
df <- df
shinyServer(function(input, output, session) {
datasetInput <- reactive({
df<- df %>%
filter(
(input$var == 'ALL' | country == input$var)&
(input$plat == 'ALL' | platform == input$plat)&
(input$media == 'ALL' | media_source == input$media)
)
})
output$text1 <- renderText({paste("Revenue: $", df() %>%
summarise(revenue = sum(price)/100)})
})
When I make single choice, the data is correct, ex) when I choose facebook for media, the revenue is 200,000, when i choose twitter, the revenue is 50,000. So I want to see 250,000 when I choose both. however, when the number is quite odd when i'm doing so, I got something like 160,000, which is hard to know how does the system calculate it. Same problems with the other two select widget.
BTW, I'm also getting this warning message:
longer object length is not a multiple of shorter object length
Anyone knows which part I did wrong? Thank you.

Resources