I am attempting to adapt an example (2.1.1) from the tutorial found here on interactive plots in shiny. I have a shiny app as follows:
Data:
seats = data.table(
ID = c("1","2","3","4","5","6"),
Row = c("A", "A", "A", "B", "B", "B"),
SeatNum = c(1,2,3,1,2,3),
y = c(1,1,1,2,2,2),
price = 45)
ui.R
fluidPage(
title = 'Select Table Rows',
h1('A Client-side Table'),
fluidRow(
column(6, DT::dataTableOutput('x1')),
column(6, plotOutput('x2', height = 500)),
column(3, verbatimTextOutput('x4')),
column(4, verbatimTextOutput('x5'))
),
hr(),
)
server.R
shinyServer(function(input, output, session) {
output$x1 = DT::renderDataTable(seats, editable = "row", server = FALSE)
# highlight selected rows in the scatterplot
output$x2 = renderPlot({
s = input$x1_rows_selected
par(mar = c(4, 4, 1, 1))
plot(seats$SeatNum, seats$y)
if (length(s)) points(seats[s, , drop = FALSE], pch = 19, cex = 2)
})
output$x4 = renderPrint({
s = input$x1_rows_selected
if (length(s)) {
cat('Combined price \n of all seats:\n\n')
cat(sum(seats[s,]$price))
}
})
output$x5 = renderPrint({
s2 = input$x1_rows_selected
if (length(s2)) {
cat('Total number of seats selected:\n\n')
cat(length(s2))
}
})
})
Upon launching the app I can select any of the first three rows and the plot reacts appropriately. However, from row 4 onwards the plot does not respond. I've played around with the if (length(s)) points(seats[s, , drop = FALSE], pch = 19, cex = 2) line but I don't understand its behavior.
The table used in the linked example has two columns only, so for the points function its unambiguous what values go to x and y. But your table has multiple columns, so the indexing seats[s, , drop=FALSE] returns the selected rows and all columns:
> seats[1:2, , drop=FALSE]
ID Row SeatNum y price
1: 1 A 1 1 45
2: 2 A 2 1 45
So, when indexing this way, points does not know what to map to x and y. You need to index the selected rows and the columns needed for points (in the correct order) to highlight points on the plot:
> seats[1:2, c("SeatNum", "y"), drop=FALSE]
SeatNum y
1: 1 1
2: 2 1
Working app:
library(shiny)
library(data.table)
library(DT)
seats = data.table(
ID = c("1", "2", "3", "4", "5", "6"),
Row = c("A", "A", "A", "B", "B", "B"),
SeatNum = c(1, 2, 3, 1, 2, 3),
y = c(1, 1, 1, 2, 2, 2),
price = 45
)
ui <-
fluidPage(title = 'Select Table Rows',
h1('A Client-side Table'),
fluidRow(
column(6, DT::dataTableOutput('x1')),
column(6, plotOutput('x2', height = 500)),
column(3, verbatimTextOutput('x4')),
column(4, verbatimTextOutput('x5'))
),
hr())
server <- function(input, output, session) {
output$x1 = DT::renderDataTable(seats, editable = "row", server = FALSE)
# highlight selected rows in the scatterplot
output$x2 = renderPlot({
s = input$x1_rows_selected
par(mar = c(4, 4, 1, 1))
plot(seats$SeatNum, seats$y)
if (length(s))
points(seats[s, c("SeatNum", "y") , drop = FALSE], pch = 19, cex = 2)
})
output$x4 = renderPrint({
s = input$x1_rows_selected
if (length(s)) {
cat('Combined price \n of all seats:\n\n')
cat(sum(seats[s, ]$price))
}
})
output$x5 = renderPrint({
s2 = input$x1_rows_selected
if (length(s2)) {
cat('Total number of seats selected:\n\n')
cat(length(s2))
}
})
}
shinyApp(ui, server)
Related
I am trying to build an app that displays tables for different years. In some years some tables do not exist. I solved this with conditionalPanel and the condition that the tables exist. This works at first. The problem is that it doesn't work once a table is retrieved that doesn't exist. You can try this on this test page (http://46.231.205.192/Tests/). After opening the app, one table per year is visible. If you go to the next table with >, the error message for 2021 is correctly displayed at the bottom. If you then go back <, the error continues to be displayed, although the table for 2021 exists in that case.
I think the problem arises from conditionalPanel with output.Table_2021 but I can't fix it.
Can you see a solution?
library(shiny)
library(DT)
Table_1 <- data.frame(Antworten = "mean", Total = 3, US = 3.5, FR = 4, IT = 2, male = 0, female = 1)
Table_2 <- data.frame(Antworten = "mean", Total = 2, US = 2.5, FR = 3, IT = 1, male = 1, female = 2)
Table_1_2021 <- data.frame(Antworten = "mean", Total = 4, US = 4.5, FR = 5, IT = 3, male = 3, female = 10)
# in 2021 the Table_2 is missing
tabnames <- c("Table_1", "Table_2")
# Columns
kopfvariablen <- c("region", "sex")
default_vars <- c("region")
# Shiny ----
ui <- fluidPage(
titlePanel(title=div("Tables")),
sidebarLayout(
sidebarPanel(width = 2, tags$style(".well {background-color: #ffffff; border-color: #ffffff}"),
a(br(), br(), br(), br()),
checkboxInput(
inputId = "year_2022",
label = "Tabs: 2022",
value = TRUE),
checkboxInput(
inputId = "year_2021",
label = "Tabs: 2021",
value = TRUE)
),
mainPanel(
align = "center",
actionButton("prevBin", "<", class="btn btn-success"),
actionButton("nextBin", ">", class="btn btn-success"),
selectInput(
inputId = "dataset",
label = "",
choices = tabnames,
width = "60%"),
conditionalPanel(
condition = "input.year_2022 == 1 ",
DT::dataTableOutput("Table_2022")),
conditionalPanel(inline = T,
condition = "input.year_2021 == 1 && output.Table_2021", # I think the problem comes with this line.
DT::dataTableOutput('Table_2021')),
conditionalPanel(inline = T,
condition = "input.year_2021 == 1 && output.Table_2021 == null",
h4("[This Question was not asked in 2021.]", align = "left", style = "color:grey"))
)
))
server = function(input, output, session) {
# "next" and "previous" buttons
output$prevBin <- renderUI({
actionButton("prevBin",
label = "Previous")
})
output$nextBin <- renderUI({
actionButton("nextBin",
label = "Next")
})
observeEvent(input$prevBin, {
current <- which(tabnames == input$dataset)
if(current > 1){
updateSelectInput(session, "dataset",
choices = as.list(tabnames),
selected = tabnames[current - 1])
}
})
observeEvent(input$nextBin, {
current <- which(tabnames == input$dataset)
if(current < length(tabnames)){
updateSelectInput(session, "dataset",
choices = as.list(tabnames),
selected = tabnames[current + 1])
}
})
# Tables 2022 -----
output$Table_2022 <- DT::renderDataTable({
# Data with names from input
data <- get(input$dataset)
data_fin <- data[,1:7]
#subheader as list
subheader <- list()
subheader <- c(subheader, "US", "FR", "IT")
subheader <- c(subheader, "male", "female")
# The header
topheader_txt <- "tr(th(rowspan = 2, 'Values'), th(rowspan = 2, 'Total') , th(class = 'dt-center', colspan = 3, 'region'), th(class = 'dt-center', colspan = 2, 'sex')"
topheader <- parse(text=paste0(topheader_txt, ")"))
#Container for topheader and subheader
sketch = htmltools::withTags(table(
class = 'display',
thead(
eval(topheader),
tr(lapply(rep(subheader, 1), th))
)
)
)
# Table with container
DT::datatable(data_fin,
container = sketch,
rownames = F)
})
# Tables 2021 -----
output$Table_2021 <- DT::renderDataTable({
#Daten aus Auswahl
data <- get(paste0(input$dataset, "_2021"))
data_fin <- data[,1:7]
#subheader list
subheader <- list()
subheader <- c(subheader, "US", "FR", "IT")
subheader <- c(subheader, "male", "female")
topheader_txt <- "tr(th(rowspan = 2, 'Values'), th(rowspan = 2, 'Total') , th(class = 'dt-center', colspan = 3, 'region'), th(class = 'dt-center', colspan = 2, 'sex')"
topheader <- parse(text=paste0(topheader_txt, ")"))
#Container for topheader and subheader
sketch = htmltools::withTags(table(
class = 'display',
thead(
eval(topheader),
tr(lapply(rep(subheader, 1), th))
)
)
)
js <- c(
"function(settings){",
" var datatable = settings.oInstance.api();",
" var table = datatable.table().node();",
" var caption = '2021'",
" $(table).append('<caption style=\"caption-side: top-right; text-align: center; margin: 8px 0; font-size: 2em\">' + caption + '</caption>');",
"}"
)
# Table with container
DT::datatable(data_fin,
container = sketch,
rownames = F,
caption = tags$caption(
style="caption-side: bottom; text-align: left; margin: 8px 0;"
),
extensions = c('Buttons'),
options = list(initComplete = JS(js))
)
})
}
shinyApp(ui, server)
The solution comes with: outputOptions(output, "Table_2021", suspendWhenHidden = FALSE) in the server function.
library(shiny)
library(DT)
Table_1 <- data.frame(Antworten = "mean", Total = 3, US = 3.5, FR = 4, IT = 2, male = 0, female = 1)
Table_2 <- data.frame(Antworten = "mean", Total = 2, US = 2.5, FR = 3, IT = 1, male = 1, female = 2)
Table_1_2021 <- data.frame(Antworten = "mean", Total = 4, US = 4.5, FR = 5, IT = 3, male = 3, female = 10)
# in 2021 the Table_2 is missing
tabnames <- c("Table_1", "Table_2")
# Columns
kopfvariablen <- c("region", "sex")
default_vars <- c("region")
# Shiny ----
ui <- fluidPage(
titlePanel(title=div("Tables")),
sidebarLayout(
sidebarPanel(width = 2, tags$style(".well {background-color: #ffffff; border-color: #ffffff}"),
a(br(), br(), br(), br()),
checkboxInput(
inputId = "year_2022",
label = "Tabs: 2022",
value = TRUE),
checkboxInput(
inputId = "year_2021",
label = "Tabs: 2021",
value = TRUE)
),
mainPanel(
align = "center",
actionButton("prevBin", "<", class="btn btn-success"),
actionButton("nextBin", ">", class="btn btn-success"),
selectInput(
inputId = "dataset",
label = "",
choices = tabnames,
width = "60%"),
conditionalPanel(
condition = "input.year_2022 == 1 ",
DT::dataTableOutput("Table_2022")),
conditionalPanel(inline = T,
condition = "input.year_2021 == 1 && output.Table_2021", # I think the problem comes with this line.
DT::dataTableOutput('Table_2021')),
conditionalPanel(inline = T,
condition = "input.year_2021 == 1 && output.Table_2021 == null",
h4("[This Question was not asked in 2021.]", align = "left", style = "color:grey"))
)
))
server = function(input, output, session) {
outputOptions(output, "Table_2021", suspendWhenHidden = FALSE) # Solution
# "next" and "previous" buttons
output$prevBin <- renderUI({
actionButton("prevBin",
label = "Previous")
})
output$nextBin <- renderUI({
actionButton("nextBin",
label = "Next")
})
observeEvent(input$prevBin, {
current <- which(tabnames == input$dataset)
if(current > 1){
updateSelectInput(session, "dataset",
choices = as.list(tabnames),
selected = tabnames[current - 1])
}
})
observeEvent(input$nextBin, {
current <- which(tabnames == input$dataset)
if(current < length(tabnames)){
updateSelectInput(session, "dataset",
choices = as.list(tabnames),
selected = tabnames[current + 1])
}
})
# Tables 2022 -----
output$Table_2022 <- DT::renderDataTable({
# Data with names from input
data <- get(input$dataset)
data_fin <- data[,1:7]
#subheader as list
subheader <- list()
subheader <- c(subheader, "US", "FR", "IT")
subheader <- c(subheader, "male", "female")
# The header
topheader_txt <- "tr(th(rowspan = 2, 'Values'), th(rowspan = 2, 'Total') , th(class = 'dt-center', colspan = 3, 'region'), th(class = 'dt-center', colspan = 2, 'sex')"
topheader <- parse(text=paste0(topheader_txt, ")"))
#Container for topheader and subheader
sketch = htmltools::withTags(table(
class = 'display',
thead(
eval(topheader),
tr(lapply(rep(subheader, 1), th))
)
)
)
# Table with container
DT::datatable(data_fin,
container = sketch,
rownames = F)
})
# Tables 2021 -----
output$Table_2021 <- DT::renderDataTable({
#Daten aus Auswahl
data <- get(paste0(input$dataset, "_2021"))
data_fin <- data[,1:7]
#subheader list
subheader <- list()
subheader <- c(subheader, "US", "FR", "IT")
subheader <- c(subheader, "male", "female")
topheader_txt <- "tr(th(rowspan = 2, 'Values'), th(rowspan = 2, 'Total') , th(class = 'dt-center', colspan = 3, 'region'), th(class = 'dt-center', colspan = 2, 'sex')"
topheader <- parse(text=paste0(topheader_txt, ")"))
#Container for topheader and subheader
sketch = htmltools::withTags(table(
class = 'display',
thead(
eval(topheader),
tr(lapply(rep(subheader, 1), th))
)
)
)
js <- c(
"function(settings){",
" var datatable = settings.oInstance.api();",
" var table = datatable.table().node();",
" var caption = '2021'",
" $(table).append('<caption style=\"caption-side: top-right; text-align: center; margin: 8px 0; font-size: 2em\">' + caption + '</caption>');",
"}"
)
# Table with container
DT::datatable(data_fin,
container = sketch,
rownames = F,
caption = tags$caption(
style="caption-side: bottom; text-align: left; margin: 8px 0;"
),
extensions = c('Buttons'),
options = list(initComplete = JS(js))
)
})
}
shinyApp(ui, server)
This post is a follow-on to yesterday's post, How to make selectInput choices reactive?.
The data frame shown at the top of the image below and generated via the MWE at the bottom of this post has two types of period measurements: Period_1 and Period_2. Period_1 represents the number of months elapsed since the element arose, and Period_2 is a calendar month representation in YYYY-MM form. I inserted a radioButton() giving the user the choice of which period type ("periodType") to run through the simple placeholder function in the server section, but am unsure of an efficient way to do this, especially in the selectizeInput() functions currently in the ui section, without resorting to renderUI(). Any suggestions for how to do this?
This image better explains:
MWE code:
library(shiny)
library(data.table)
DT <- data.table(
ID = c(1, 1, 1, 2, 2, 2, 3, 3, 3),
Period_1 = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
Period_2 = c("2020-01","2020-02","2020-03","2020-02","2020-03","2020-04","2020-03","2020-04","2020-05"),
Values = c(5, 10, 15, 0, 2, 4, 3, 6, 9)
)
all_choices <- function(x) {unique(x)}
ui <- fluidPage(
tableOutput("data"),
radioButtons("periodType",
label = "Period type selection:",
choiceNames = c('Period_1','Period_2'),
choiceValues = c('Period_1','Period_2'),
selected = 'Period_1',
inline = TRUE
),
selectizeInput(
inputId = "fromPeriod",
label = "From period:",
choices = setdiff(all_choices(DT$Period_1), last(all_choices(DT$Period_1))),
selected = 1
),
selectizeInput(
inputId = "toPeriod",
label = "To period:",
choices = setdiff(all_choices(DT$Period_1), first(all_choices(DT$Period_1))),
selected = 2
),
tableOutput("dataSelect")
)
server <- function(input, output, session) {
output$data <- renderTable({DT})
observeEvent(input$fromPeriod, {
freezeReactiveValue(input, "toPeriod")
updateSelectizeInput(
session,
inputId = "toPeriod",
choices = all_choices(DT$Period_1)[all_choices(DT$Period_1) > input$fromPeriod],
selected = max(all_choices(DT$Period_1)[all_choices(DT$Period_1) > input$fromPeriod])
)
}, ignoreInit = TRUE)
output$dataSelect <- renderTable({
setorder(DT[Period_1 %in% c(input$fromPeriod, input$toPeriod)], Period_1)
}, rownames = TRUE)
}
shinyApp(ui, server)
We can update the choices based on the selection:
library(shiny)
library(data.table)
DT <- data.table(
ID = c(1, 1, 1, 2, 2, 2, 3, 3, 3),
Period_1 = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
Period_2 = c("2020-01","2020-02","2020-03","2020-02","2020-03","2020-04","2020-03","2020-04","2020-05"),
Values = c(5, 10, 15, 0, 2, 4, 3, 6, 9)
)
all_choices_p1 <- unique(DT$Period_1)
all_choices_p2 <- unique(DT$Period_2)
ui <- fluidPage(
tableOutput("data"),
radioButtons("periodType",
label = "Period type selection:",
choiceNames = c('Period_1','Period_2'),
choiceValues = c('Period_1','Period_2'),
selected = 'Period_1',
inline = TRUE
),
selectizeInput(
inputId = "fromPeriod",
label = "From period:",
choices = all_choices_p1[-length(all_choices_p1)],
selected = 1
),
selectizeInput(
inputId = "toPeriod",
label = "To period:",
choices = all_choices_p1[-1],
selected = 2
),
tableOutput("dataSelect")
)
server <- function(input, output, session) {
all_choices_reactive <- reactiveVal(all_choices_p1)
output$data <- renderTable({DT})
observeEvent(input$periodType, {
if(input$periodType == "Period_1"){
all_choices_reactive(all_choices_p1)
} else {
all_choices_reactive(all_choices_p2)
}
updateSelectizeInput(
session,
inputId = "fromPeriod",
choices = all_choices_reactive()[-length(all_choices_reactive())]
)
updateSelectizeInput(
session,
inputId = "toPeriod",
choices = all_choices_reactive()[-1]
)
})
observeEvent(input$fromPeriod, {
freezeReactiveValue(input, "toPeriod")
updateSelectizeInput(
session,
inputId = "toPeriod",
choices = all_choices_reactive()[all_choices_reactive() > input$fromPeriod],
selected = max(all_choices_reactive()[all_choices_reactive() > input$fromPeriod])
)
}, ignoreInit = TRUE)
output$dataSelect <- renderTable({
if(input$periodType == "Period_1"){
keep_cols <- c("ID", "Period_1", "Values")
setorder(DT[Period_1 %in% c(input$fromPeriod, input$toPeriod), ..keep_cols], Period_1)
} else {
keep_cols <- c("ID", "Period_2", "Values")
setorder(DT[Period_2 %in% c(input$fromPeriod, input$toPeriod), ..keep_cols], Period_2)
}
}, rownames = TRUE)
}
shinyApp(ui, server)
I am constructing a shiny app. In the UI I have one selectInput and one pickerInput. Of course the pickerInput depends on the selectInput. In the example below, I want to find a way how to preserve what has been selected in pickerInput when users change the selectInput.
In the example below, let's imagine a user who selects Period 1: X to Z and either UK or USA or both UK and USA. What I want is that if that user changes Period 1: X to Z to Period 2: X to Y that UK be automatically selected -- or stay selected -- (because UK is among the choices of Period 2: X to Y).
So, how to retain what has been selected in pickerInput when input_period changes.
Thank you!
choice_name <- c('UK','USA','UK','USA','BE','BE')
choice_id <- c(1, 2, 1, 2, 3, 3)
period <- c('period1', 'period1', 'period2', 'period3', 'period3', 'period3')
data <- data.frame(choice_name, choice_id, period)
choices_picker <- unique(data$choice_id)
names(choices_picker) <- unique(data$choice_name)
ui <- bootstrapPage(
absolutePanel(left = 10, bottom = 10, draggable = TRUE,
selectInput(inputId = "input_period", label = "Period",
choices = c("Period 1: X to Z" = "period1", "Period 2: X to Y" = "period2", "Period 3: X to X" = "period3"),
selected = "period1"),
pickerInput(inputId = "picker_cty",
label = "Select Country",
choices = choices_picker,
multiple = TRUE),
))
server <- function(input, output, session) {
# Reactive pickerInput ---------------------------------
observeEvent(input$input_period, {
data1 <- data[data$period == input$input_period,]
datau <- unique(data$choice_id)
data1u <- unique(data1$choice_id)
disabled_choices <- ifelse(datau %in% data1u, 0,1)
# Generate reactive picker input
updatePickerInput(session = session,
inputId = "picker_cty",
choices = choices_picker,
choicesOpt = list(
disabled = disabled_choices,
style = ifelse(disabled_choices,
yes = "color: rgba(119, 119, 119, 0.5);",
no = "")
))
}, ignoreNULL=FALSE)
}
shinyApp(ui, server)
You can use select = option. Try this
choice_name <- c('UK','USA','UK','USA','BE','BE')
choice_id <- c(1, 2, 1, 2, 3, 3)
period <- c('period1', 'period1', 'period2', 'period3', 'period3', 'period3')
data <- data.frame(choice_name, choice_id, period)
data2 <- data[data$period == "period1",]
choices_picker <- unique(data$choice_id)
names(choices_picker) <- unique(data$choice_name)
datau <- unique(data$choice_id)
data2u <- unique(data2$choice_id)
disabled_choicez <- ifelse(datau %in% data2u, 0,1)
ui <- bootstrapPage(
absolutePanel(left = 10, bottom = 10, draggable = TRUE,
selectInput(inputId = "input_period", label = "Period",
choices = c("Period 1: X to Z" = "period1", "Period 2: X to Y" = "period2", "Period 3: X to X" = "period3"),
selected = "period1" ),
pickerInput(inputId = "picker_cty",
label = "Select Country",
choices = choices_picker,
choicesOpt = list(
disabled = disabled_choicez,
style = ifelse(disabled_choicez,
yes = "color: rgba(119, 119, 119, 0.5);",
no = "")
),
selected = character(0),
multiple = TRUE),
))
server <- function(input, output, session) {
observe({print(input$picker_cty)})
# Reactive pickerInput ---------------------------------
observeEvent(input$input_period, {
data1 <- data[data$period == input$input_period,]
datau <- unique(data$choice_id)
data1u <- unique(data1$choice_id)
disabled_choices <- ifelse(datau %in% data1u, 0,1)
if (is.null(input$picker_cty)) selected = character(0)
else {
if (sum(data1u %in% input$picker_cty)>0) {
selected = data1u[data1u %in% input$picker_cty]
}else selected = character(0)
}
# Generate reactive picker input
updatePickerInput(session = session,
inputId = "picker_cty",
choices = choices_picker,
selected = selected,
choicesOpt = list(
disabled = disabled_choices,
style = ifelse(disabled_choices,
yes = "color: rgba(119, 119, 119, 0.5);",
no = "")
))
}, ignoreInit = TRUE)
}
shinyApp(ui, server)
I'm new to R and shiny. I have a problem that I could not solve.
I have a histogram where I want to make the classes separately selectable.
The classes are all in one column. To make them separately selectable, I did not succeed.
How do I get it to work?
Thanks a lot
## app.R ##
set.seed(24)
df <- data.frame(Class = sample(LETTERS[1:5], 30, replace = TRUE),
Amount = sample(5:20, 30, replace = TRUE),
stringsAsFactors= FALSE, check.names = FALSE)
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$obs), col = 'darkgray', border = 'white')
})
output$sum = renderPrint({
summary(df)
})
output$str = renderPrint({
str(df)
})
output$data = renderTable({
colm = as.numeric(input$var)
df[colm]
head(df)
})
output$myhist <- renderPlot({
colm = as.numeric(input$var)
hist(df$Amount, col =input$colour, xlim = c(0, max(df$Amount)), main = "Histogram", breaks = seq(0, max(df$Amount),l=input$bin+1),
xlab = names(df$Amount)
)}
)
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("var", label = "1. Select Class",
choices = c("A" = 1, "B" = 2, "C" = 3, "D"= 4, "E" = 5),
selected = 2),
sliderInput("bin", "2. Select the number of histogram BINs by using the slider below", min=5, max=25, value=15),
radioButtons("colour", label = "3. Select the color of histogram",
choices = c("Green", "Red",
"Blue"), selected = "Green")
),
mainPanel(
tabsetPanel(type="tab",
tabPanel("Plot", plotOutput("myhist")),
tabPanel("Summary", verbatimTextOutput("sum")),
tabPanel("Structure", verbatimTextOutput("str")),
tabPanel("Data", tableOutput("data"))
)
)
)
)
shinyApp(ui = ui, server = server)
I appreciate your help.
You have a few options:
Allow the selectInput to have multiple selections, by adding multiple = TRUE:
selectInput("var", label = "1. Select Class", choices = c("A" = 1, "B" = 2, "C" = 3, "D"= 4, "E" = 5), multiple = TRUE)
Use a checkbox group:
checkboxGroupInput('var', label = "1. Select Class", choices = c("A" = 1, "B" = 2, "C" = 3, "D"= 4, "E" = 5))
I recommend the 2nd option, using a checkbox group, as I believe they are easy for users to understand.
EDIT
As requested here is the full code, with the checkbox group linked to the chart:
## app.R ##
library(shiny)
set.seed(24)
df <- data.frame(Class = sample(LETTERS[1:5], 30, replace = TRUE),
Amount = sample(5:20, 30, replace = TRUE),
stringsAsFactors= FALSE, check.names = FALSE)
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$obs), col = 'darkgray', border = 'white')
})
output$sum = renderPrint({
summary(df)
})
output$str = renderPrint({
str(df)
})
output$data = renderTable({
colm = as.numeric(input$var)
df[colm]
head(df)
})
output$myhist <- renderPlot({
df_plot <- df[df$Class %in% input$var, ]
hist(df_plot$Amount, col = input$colour, xlim = c(0, max(df_plot$Amount)), main = "Histogram", breaks = seq(0, max(df_plot$Amount),l=input$bin+1),
xlab = names(df_plot$Amount)
)}
)
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
checkboxGroupInput('var', label = "1. Select Class", choices = c("A", "B", "C", "D", "E"), selected = "B"),
sliderInput("bin", "2. Select the number of histogram BINs by using the slider below", min=5, max=25, value=15),
radioButtons("colour", label = "3. Select the color of histogram",
choices = c("Green", "Red",
"Blue"), selected = "Green")
),
mainPanel(
tabsetPanel(type="tab",
tabPanel("Plot", plotOutput("myhist")),
tabPanel("Summary", verbatimTextOutput("sum")),
tabPanel("Structure", verbatimTextOutput("str")),
tabPanel("Data", tableOutput("data"))
)
)
)
)
shinyApp(ui = ui, server = server)
I have a basic shiny app that evaluates A + B:
library(shiny)
ui <- fluidPage(
numericInput(inputId = "A", label = "A", value = 5, step = 1),
sliderInput(inputId = "B", label = "B", min = 0, max = 10, value = 5),
textOutput(outputId = "value")
)
server <- function(input, output) {
output$value <- renderText(paste0("A + B = ", input$A + input$B))
}
shinyApp(ui = ui, server = server)
A is a numericInput value and B is a sliderInput value.
I want to constrain my app so that the maximum input value for B is always 2 * A. I, therefore, must change the hardcoded max = in sliderInput to something that can be dynamic. How can I accomplish this?
Thanks
You can call updateSliderInput to change the maximum value for B from within an observe which will be triggered whenever A changes:
library(shiny)
ui <- fluidPage(
numericInput(inputId = "A", label = "A", value = 5, step = 1),
sliderInput(inputId = "B", label = "B", min = 0, max = 10, value = 5),
textOutput(outputId = "value")
)
# Notice the session argument to be passed to updateSliderInput
server <- function(input, output, session) {
output$value <- renderText(paste0("A + B = ", input$A + input$B))
observe(updateSliderInput(session, "B", max = input$A*2))
}
shinyApp(ui = ui, server = server)
You are looking for renderUI()
library(shiny)
ui <- fluidPage(
numericInput(inputId = "A", label = "A", value = 5, step = 1),
uiOutput("slider"),
textOutput(outputId = "value")
)
server <- function(input, output) {
output$value <- renderText(paste0("A + B = ", input$A + input$B))
output$slider <- renderUI({
sliderInput(inputId = "B", label = "B", min = 0, max = 2*input$A, value = 5)
})
}
shinyApp(ui = ui, server = server)