r shiny - How to display a variable number of numeric inputs - r

I would like to display a variable number of inputs based on a numeric input "number of lines". As there can be potentially a large number of lines, I don't want to use a conditional panel for each line and would rather iterate with functions as below:
ui <- fluidPage(
lapply(1:3,function(iter1){
fluidRow(
column(2,
h4(paste0("line", iter1))
),
lapply(1:4,function(iter2){
column(2,
h4(paste0("Wind speed bin", iter2)),
column(6, numericInput(paste0("v", iter1,"bin",iter2,"min"),"Vmin",5)),
column(6, numericInput(paste0("v", iter1, "bin",iter2,"max"),"Vmax",6))
)
})
)
})
)
The code above allows to display 4 wind speed bins definitions per line j (numericInput: vjbin1min, vjbin1max, vjbin2min, vjbin2max, ...) on 3 lines.
Overview of sidebar layout
I would like now to define the number of bins [of lines] with a variable bin_nb [line_nb] as below:
lapply(1:bin_nb,function(iter1){...
lapply(1:line_nb,function(iter2){...
With two numeric inputs
numericInput("bin_nb","number of wind speed bins",value=4),
numericInput("line_nb","number of lines",value=3)
I have tried to get the value from server side
output$bin_nb <- renderText(input$bin_nb)
And use
lapply(1:textOutput("bin_nb"),function(iter1){...
Which is of course not working as a numeric value is requested. How could I define and use these two numeric variables bin_nb and line_nb?

Based on BigDataScientist's comment, here is the detailed solution:
ui <- fluidPage(
numericInput("line_nb","number of lines",value=3),
numericInput("bin_nb","number of wind speed bins",value=4),
uiOutput("input_panel")
)
And server side:
server <- function(input, output) {
output$input_panel <- renderUI({
lapply(1:input$line_nb,function(iter1){
fluidRow(
column(2,
h4(paste0("line", iter1))
),
lapply(1:input$bin_nb,function(iter2){
column(2,
h4(paste0("Wind speed bin", iter2)),
column(6, numericInput(paste0("v", iter1,"bin",iter2,"min"),"Vmin",5)),
column(6,numericInput(paste0("v", iter1, "bin",iter2,"max"),"Vmax",6))
)
})
)
})
})
}

Related

how to use conditionalpanel() in shiny r

I am trying to create a shiny app where it allows you to select an input of what operation calculate. if the user chooses "Addition" it will show the two numeric input boxes (so they can input two numbers), if the user chooses "square" it will show only one numeric input box to square.
With this, I use conditionalPanel and if the condition is satisfied, it fetches through uiOutput() the numericInputs that I want. and same thing for square.
Now when I run this app, the conditional panels do not appear. Where did I go wrong? Thanks for checking out my question.
ui <- fluidPage( theme = shinytheme("slate"),
titlePanel("Basic Calculator"),
sidebarPanel(
selectInput("ops","Select what Operation use",choices = c("ADDITION","SQUARE")),
helpText("Please input the appropriate number depending on the operations"),
conditionalPanel("input.ops=='ADDITION'", uiOutput("var2")),
conditionalPanel("input.ops=='SQUARE'", uiOutput("var1"))
),#sidebar panel
)#fluidpage
server <- function(input, output) {
output$basicmath <- renderText( ifelse(input$ops=="ADDITION",input$a+input$b,
ifelse(input$ops=="SUBTRACTION",input$a-input$b,
ifelse(input$ops=="SQUARE",input$a*input$a,
ifelse(input$ops=="SQUARE ROOT",sqrt(input$a),
ifelse(input$ops=="MULTIPLICATION",input$a*input$b,"not a valid operation"))))),
output$var2 <- renderUI({
helpText("this will show to input two numerics to be added")
}) ,
output$var1 <- renderUI({
helpText("this will show to input one numeric to square")
})
)}
shinyApp(ui = ui, server = server)
The key issue you were having is that you put the uiOutputs inside the calculation output that you anticipated. It is better to separate them, since the calculation output won't run until it has the necessary prerequisite values (your input values). In addition, because you hadn't specified an output location for basicmath, the app didn't know where to put anything inside that call to renderText(). Below is working code that gets the right UI elements to appear.
One other thing you were missing in your renderUI was the use of tagList(). This helps ensure that all of your elements are packaged together, not just the last one.
Note that the math part does not work, but it looks like that was just a placeholder. When you do start to use it, be sure to use unique ids for each input. You have several instances of input$a and input$b, which probably isn't a workable approach.
library(shiny)
library(shinythemes)
ui <- fluidPage( theme = shinytheme("slate"),
titlePanel("Basic Calculator"),
sidebarPanel(
selectInput("ops","Select what Operation use",choices = c("ADDITION","SQUARE")),
helpText("Please input the appropriate number depending on the operations"),
conditionalPanel("input.ops=='ADDITION'", uiOutput("var2")),
conditionalPanel("input.ops=='SQUARE'", uiOutput("var1"))
),
mainPanel(
textOutput("basicmath")
)
)#fluidpage
server <- function(input, output) {
output$var2 <- renderUI({
tagList(
helpText("this will show to input two numerics to be added"),
splitLayout(
numericInput("var2a", label = "Input one number", value = NULL),
numericInput("var2b", label = "Input another number", value = NULL)
)
)
})
output$var1 <- renderUI({
tagList(
helpText("this will show to input one numeric to square"),
numericInput("var1a", label = "Input a number", value = NULL)
)
})
output$basicmath <- renderText( {ifelse(input$ops=="ADDITION",input$a+input$b,
ifelse(input$ops=="SUBTRACTION",input$a-input$b,
ifelse(input$ops=="SQUARE",input$a*input$a,
ifelse(input$ops=="SQUARE ROOT",sqrt(input$a),
ifelse(input$ops=="MULTIPLICATION",input$a*input$b,"not a valid operation")))))
})
}
shinyApp(ui = ui, server = server)

No output in shiny

I try to print out text in information section, to plot graphs separately for cases and deaths of cover 19 and make a summary table for each month in summary section.
But now, only sidebar shows, text and graphs don't show up at all.
I guess there are mistakes in server.R
But,I check code several times and still have no idea what the problem is. Does anyone can help?
ui.R
library(shiny)
library(ggplot2)
library(dplyr)
data<-read.csv('https://raw.githubusercontent.com/lingling1123/covid-19-data/master/us.csv')
data$date<-as.numeric(as.Date(data$date,origin='2020-01-21'))-18281
data$cases<-data$cases/1000
data$deaths<-data$deaths/1000
Jan<-c(1:11)
Feb<-c(12:40)
Mar<-c(41:71)
Apr<-c(72:101)
May<-c(102:132)
Jun<-c(133:162)
Jul<-c(163:193)
Aug<-c(194:224)
Sep<-c(225:254)
Oct<-c(255:285)
Nov<-c(286:298)
# Define UI for application that draws a histogram
shinyUI(navbarPage('All you can know',
# Information
tabPanel('Information',
mainPanel(
textOutput("info"),
)
),
# Summaries
tabPanel('Summaries',
sidebarLayout(
sidebarPanel(
h4('You can create plots using the radio buttons below.'),
radioButtons('var',h5('Select the variable '),choices=list('cases','deaths')),
h4('You can create numerical summaries below.'),
selectizeInput("mon", h5('Select the month you want to check'),selected = "Jan", choices = c('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct'))
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
tableOutput("table")
)
)
)))
server.R
shinyServer(function(input,output,session) {
output$info <- renderPrint({
print('For this project, I use Covid19 dataset that incluses date, cases and deaths to make a exposure notification app.')
})
value<-reactive({
variables<-input$var
})
output$distPlot <- renderPlot({
if(value()=='cases'){
ggplot(data,aes(x=date,y=cases))+geom_point()
}else{
ggplot(data,aes(x=date,y=deaths))+geom_point()
}
}
)
}
)
Move the data load section from your ui.r to server.r, e.g.
ui.r
library(shiny)
library(ggplot2)
library(dplyr)
# Define UI for application that draws a histogram
shinyUI(navbarPage('All you can know',
# Information
tabPanel('Information',
mainPanel(
textOutput("info"),
)
),
# Summaries
tabPanel('Summaries',
sidebarLayout(
sidebarPanel(
h4('You can create plots using the radio buttons below.'),
radioButtons('var',h5('Select the variable '),choices=list('cases','deaths')),
h4('You can create numerical summaries below.'),
selectizeInput("mon", h5('Select the month you want to check'),selected = "Jan", choices = c('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct'))
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot"),
tableOutput("table")
)
)
)))
server.r
data<-read.csv('https://raw.githubusercontent.com/lingling1123/covid-19-data/master/us.csv')
data$date<-as.numeric(as.Date(data$date,origin='2020-01-21'))-18281
data$cases<-data$cases/1000
data$deaths<-data$deaths/1000
Jan<-c(1:11)
Feb<-c(12:40)
Mar<-c(41:71)
Apr<-c(72:101)
May<-c(102:132)
Jun<-c(133:162)
Jul<-c(163:193)
Aug<-c(194:224)
Sep<-c(225:254)
Oct<-c(255:285)
Nov<-c(286:298)
shinyServer(function(input,output,session) {
output$info <- renderPrint({
print('For this project, I use Covid19 dataset that incluses date, cases and deaths to make a exposure notification app.')
})
value<-reactive({
variables<-input$var
})
output$distPlot <- renderPlot({
if(value()=='cases'){
ggplot(data,aes(x=date,y=cases))+geom_point()
}else{
ggplot(data,aes(x=date,y=deaths))+geom_point()
}
}
)
}
)

Arranging textInput elements in two or more columns in a shiny app

The Shiny GUI right now looks as in the attached figure.
I would like to optimize the space and arrangment of the (>30) textInput elements in two or more columns in the sidebarPanel.
How do I set up two columns with the textInput elements - is there a table type I can use?
How to change textInput height, I can see that only 'width' can be edited?
How to optimize the textInput elements arrangment: i.e. distance between elements, font size etc?
The code shows a two column and 15 rows (30 textInputs) sidebar design. Basically, you write a function to generate UI for one row and then just call it again and again using lapply for however many rows you want. You can use this approach for any number of columns.
output$test shows how you can extract values from all inputs.
library(shiny)
textInputFUN <- function(uid) {
fluidRow(
column(6,
textInput(paste0("par_", uid), label = paste0("par_", uid))
),
column(6,
textInput(paste0("par_", uid+1), label = paste0("par_", uid+1))
)
)
}
input_rows <- 15
input_ids <- seq(1, input_rows*2, by = 2)
shinyApp(
ui = fluidPage(
sidebarLayout(
sidebarPanel(
lapply(seq_len(input_rows), function(x) {
textInputFUN(uid = input_ids[x])
})
),
mainPanel(
verbatimTextOutput("test")
)
)
),
server = function(input, output, session) {
output$test <- renderPrint({
sapply(paste0("par_", seq_len(input_rows*2)), function(x) input[[x]])
})
}
)

R get value from selectInput updated

I have a selectInpunt updated, and with this last value, I want to get information from a dataframe, but I can't get the value of the last selectInput, I have just the result "character(0)". The dataframe open but I can't get the value corresponding to input...The values of the first selectInput are the names of different data.frames. I can get the data.frame, but I can not extract the information corresponding to the input of the second selectInput.
library(shiny)
liste<-c("BCE","FED")
ui<-tagList(
navbarPage(
"Evolutions Economiques",
tabPanel("Observation",
# Application title
titlePanel("Evolutions Economiques"),
# Sidebar with a slider input for number of bins
#sidebarLayout(
sidebarPanel(
h1("Selection des donnees"),
selectInput("Source","Source :",
choices =liste),
selectInput("indic","Indicateur :",
choices = NULL)
),
# Show a plot of the generated distribution
mainPanel(
tabsetPanel(type="tabs",
tabPanel("Description",verbatimTextOutput("summary"),
)
))
)
))
library(shiny)
library(dplyr)
BCE<-data.frame(Indice=c("A","B"),Description=c("Alors","Pouipoui"))
FED<-data.frame(Indice=c("C","D"),Description=c("So","Birdyy"))
# Define server logic required to draw a histogram
shinyServer(function(input, output,session) {
observeEvent(input$Source,{
data<-get(input$Source)
updateSelectInput(session,"indic",
choices = data$Indice)
})
output$summary<-renderPrint({
data<-get(input$Source)
data<-filter(data,Indice==input$indic)
data<-data$Description
data
})
})

How to validate user input in shiny

I'm working on a very simple Shiny app that takes in a DNA codon and returns the corresponding amino acid. My issue is that I want to validate the user input so that it can only accept 3 letter (a single codon), must be capital letters, and only accept the DNA bases ( A, C, T, or G). I've had a look at Shiny's validation article, but keep on running into errors.
Here is the code I have so far:
ui.R
library(shiny)
library(shinythemes)
shinyUI(fluidPage(
theme = shinytheme("slate"),
# Application title
titlePanel("Codon lookup"),
#
sidebarLayout(
sidebarPanel(
textInput(
inputId = "codon",
label = "Enter a codon",
value = ""),
actionButton(inputId = "go", label = "Search")
),
#
mainPanel(
verbatimTextOutput("aminoacid")
)
)
))
server.R
library(shiny)
library(Biostrings)
shinyServer(function(input, output) {
data <- eventReactive(input$go, {
#validate somehow
input$codon
})
output$aminoacid <- renderText({
GENETIC_CODE[[as.character(data())]]
})
})
Also, if anyone know of an easy way to retrieve the amino acid's full name, rather than just the single letter notation, that would be helpful. Any other suggestions are welcomed.
That reactive is not really the right place to do the validation in this case since you are not using GENETIC_CODE there. So I moved it into the renderText output node. If you had a reactive doing the lookup you could do it there.
I looked at GENETIC_CODE, and it seems to make more sense to do this as a dropdown anyway and use that as validation. So I went ahead and put a selectInput in there using renderUI, as you have more flexibility if you create the input control in the server usually.
I also moved the Search button to above the codon select control as it was getting covered up by the selection.
library(shiny)
library(shinythemes)
u <- shinyUI(fluidPage(
theme = shinytheme("slate"),
# Application title
titlePanel("Codon lookup"),
#
sidebarLayout(
sidebarPanel(
actionButton(inputId = "go", label = "Search"),
uiOutput("codonselection")
),
#
mainPanel(
verbatimTextOutput("aminoacid")
)
)
))
library(Biostrings)
s <- shinyServer(function(input, output) {
data <- eventReactive(input$go, {
input$codon
})
output$codonselection <- renderUI({
choices <- names(GENETIC_CODE)
default <- "TTC"
selectInput("codon",label="Select Codon",choices=choices,selected=default)
})
output$aminoacid <- renderText({
lookupcodon <-as.character(data())
if (lookupcodon %in% names(GENETIC_CODE)){
return(GENETIC_CODE[[ lookupcodon ]])
} else {
return("Name not in GENETIC_CODE")
}
})
})
shinyApp(u,s)
Screen shot of it working:

Resources