Shiny: how to use checkBoxGroupInput() to reactively change a bar chart - r

I'm pretty new to shiny and am struggling on how to use check boxes to update values in a bar chart. The idea I'm after is when a user ticks on a check box, a numerical value is generated that will be added to an aggregate from other inputs to make a bar chart. Here is the code I have gotten to work so far:
library(shiny)
ui <- fluidPage(
titlePanel("TCO Calculator"),
mainPanel(
sidebarPanel(
helpText("Product 1 information:"),
numericInput(
inputId = "price_1",
label = "Purchase Price",
value = "0",
min = 0,
width = '50%'
),
numericInput(
inputId = "install_1",
label = "Installation cost",
value = "0",
min = 0,
width = '50%'
),
selectInput("disposal_1", "Disposal Cost",
choices = list(Buyback = (10),
Dump = (30),
Reuse = (5)),
width = '50%'),
checkboxGroupInput("maint_1", "Maintenance:",
choices = c("Waxing",
"Stripping", "Burnishing"),
selected = NULL)
),
sidebarPanel(
helpText("Product 2 information:"),
numericInput(
inputId = "price_2",
label = "Purchase Price",
value = "0",
min = 0,
width = '50%'
),
numericInput(
inputId = "install_2",
label = "Installation cost",
value = "0",
min = 0,
width = '50%'
),
# make list?
selectInput("disposal_2", "Disposal Cost",
choices = list(Buyback = (10),
Dump = (30),
Reuse = (5)),
width = '50%'),
checkboxGroupInput("maint_2", "Maintenance:",
choices = NULL,
selected = NULL,
inline = FALSE,
width = NULL,
choiceNames = c("Waxing",
"Stripping", "Burnishing"),
choiceValues = c(10, 20, 40))
),
plotOutput("costPlot")))
server <- function(input, output, session) {
# aggregate inputs into reactive bar chart values.
select_price <- reactive({
c(input$price_1 + input$install_1
+ as.numeric(input$disposal_1),
input$price_2 + input$install_2 +
as.numeric(input$disposal_2))
})
# Bar chart.
my_bar <- output$costPlot <- renderPlot({
barplot(select_price(),
beside = T,
border=F,
las=2 ,
col=c(rgb(0.3,0.1,0.4,0.6) ,
rgb(0.3,0.5,0.4,0.6)) ,
space = 3,
ylab = "Total cost per square foot, US Dollar")
abline(v=c(4.9 , 6.1) , col="grey")
legend("top", legend = c("Product 1", "Product 2" ),
col = c(rgb(0.3,0.1,0.4,0.6),
rgb(0.3,0.5,0.4,0.6)),
bty = "n",
pch=20 , pt.cex = 4,
cex = 1.6, horiz = FALSE,
inset = c(0.05, 0.05))
my_bar
})
}
shinyApp(ui = ui, server = server)
I've been successful with the numericInput and selectInput stuff so far, I am having trouble putting together a concise way to include check boxes (with corresponding numeric values) into a reactive function that I can path into select_price(), like I have done with the numeric and selectBox stuff. Things go sideways when I try to map from other examples. I feel like there is an elegant, or in least working solution that exists. Any insight towards how to solve this would be so appreciated, thanks!

I am not sure whether this entirely solves all your problems but try this:
For maint_2, you correctly separate choiceNames and choiceValues. For maint_1 you dont't
checkboxGroupInput("maint_1", "Maintenance:",
choices = NULL,
selected = NULL,
choiceNames = c("Waxing", "Stripping", "Burnishing"),
choiceValues = c(10, 20, 40))
Then you can add input$maint_1 and input$maint_2 to your reactive (also wrapped in as.numeric(). I also use sum for + as you don't have a default for input$maint_1 and input$maint_2. sum evaluates this to 0 while + throws an error.
select_price <- reactive({
c(sum(input$price_1, input$install_1, as.numeric(input$disposal_1), as.numeric(input$maint_1)),
sum(input$price_2, input$install_2, as.numeric(input$disposal_2), as.numeric(input$maint_1)))
})

Related

Using renderText under certain condition Shiny

i'm newly to the R world and i'm just trying to build a Dashboard on Shiny.
My problem is that i want to display some text only if certain conditions are met in the renderplotly function.
shinyUI(fluidPage(
titlePanel("Posti occupati in terapia intensiva"),
sidebarLayout(
sidebarPanel(
selectInput("region","Scegli regione",unique(as.character(region_dataset$denominazione_regione),)
),
dateInput("day","Scegli data", min=region_dataset$data[1], max=region_dataset$data[nrow(region_dataset)], format="dd/mm/yyyy",value=region_dataset$data[nrow(region_dataset)]
),
),
mainPanel(
plotlyOutput(outputId = "TI"),
textOutput(outputId= "text")
)
),
))
This is the ui page and i show you the server
shinyServer(function(input, output) {
output$TI <- renderPlotly({
day <- input$day
region <- input$region
request <- filter(region_dataset,region_dataset$data==day & region_dataset$denominazione_regione==region)
plot_ly(as.data.frame(request$terapia_intensiva),
domain = list(x = c(0, 1), y = c(0, 1)),
value = request$terapia_intensiva,
title = list(text = "Posti occupati TI"),
type = "indicator",
mode = "gauge+number+delta",
delta = (reference = as.integer(request$terapia_intensiva[nrow(request$data)-1])),
gauge = list(
axis =list(range = list(NULL, request$posti_TI)),
bar = list(color = "darkmagenta"),
borderwidth = 3,
steps = list(
list(range = c(0, 0.33*request$posti_TI), color = "green"),
list(range = c(0.33*request$posti_TI, 0.66*request$posti_TI), color = "yellow"),
list(range = c(0.66*request$posti_TI, request$posti_TI), color = "red")),
threshold = list(
line = list(color = "cyan", width = 5),
thickness = 0.75,
value = request$posti_TI)))
})
output$text <- renderText("Numero massimo di posti occupati")
})
My problem is that i want to display the text in the panel only if request$terapia_intensiva>request$posti_TI
I can't find out a solution to this problem, i've tried using reactive function and conditional panel but with no results.
Thanks for helping.
renderText() can contain logic, so
output$text <- renderText({
if (request$terapia_intensiva>request$posti_TI) "Numero massimo di posti occupati"
})
If the if() returns FALSE, renderText returns NULL. If you want to be explicit, you can always add else NULL or else rturn(NULL) if you wish.

How to trigger observeEvent and action with different input types in R Shiny?

What I have
I made a Shiny app that shows a plot with some points.
You can manually change the y axis. There is a button that allows to automatically adjust the y axis so it fits the data. There is a drop-down box that allows you to select data.
I have this code:
library(shiny)
# user interface ----------------------------------------------------------
ui <- fluidPage(
fluidRow(plotOutput("myplot")),
tabsetPanel(
tabPanel(
"Input",
fluidRow(
column(
2,
numericInput(inputId = "ymax", label = "y-axis maximum", value = 30),
numericInput(inputId = "ymin", label = "y-axis minimum", value = 9),
actionButton("fity", label = "zoom to fit")
),
column(
2,
selectInput(inputId = "yaxis", label = "y-axis",
choices = list("1 to 5" = 1,
"3 to 7" = 2)
),
checkboxInput("mybx", label = "checkbox", value = TRUE)
)
)
),
fluidRow()
)
)
# server function ---------------------------------------------------------
server <- function(input, output, session) {
ydata <- reactive({
switch(input$yaxis,
"1" = {
updateCheckboxInput(session, "mybx", value = TRUE)
1:5},
"2" = {
updateCheckboxInput(session, "mybx", value = FALSE)
3:7}
)
})
observeEvent(input$fity, {
newymax <- trunc(max(ydata())) + 1
newymin <- trunc(min(ydata()))
updateNumericInput(session, "ymax", value = newymax)
updateNumericInput(session, "ymin", value = newymin)}
)
output$myplot <- renderPlot({
par(mar = c(4, 4, 0.1, 0.1))
plot(x = 1:5, y = ydata(), ylim = c(input$ymin, input$ymax))
})
}
shinyApp(ui = ui, server = server)
What I want to do
I want that the fit-y-axis code triggered by the action button will also be triggered when I'm changing the data with the dropdown box.
Things I've tried:
This. But I think it doesn't like getting a selectInput together with the button.
Putting the fit-y-axis code into a separate function, calling the function from both ydata <- reactive and observeEvent. Did not work. Cries about recursion (obviously - it's calling ydata again from inside ydata!).
Any help would be appreciated.
Why not just have another observeEvent that monitors the change in the yaxis input?
library(shiny)
# user interface ----------------------------------------------------------
ui <- fluidPage(
fluidRow(plotOutput("myplot")),
tabsetPanel(
tabPanel(
"Input",
fluidRow(
column(
2,
numericInput(inputId = "ymax", label = "y-axis maximum", value = 30),
numericInput(inputId = "ymin", label = "y-axis minimum", value = 9),
actionButton("fity", label = "zoom to fit")
),
column(
2,
selectInput(inputId = "yaxis", label = "y-axis",
choices = list("1 to 5" = 1,
"3 to 7" = 2)
),
checkboxInput("mybx", label = "checkbox", value = TRUE)
)
)
),
fluidRow()
)
)
server <- function(input, output, session) {
ydata <- reactive({
switch(input$yaxis,
"1" = {
updateCheckboxInput(session, "mybx", value = TRUE)
1:5},
"2" = {
updateCheckboxInput(session, "mybx", value = FALSE)
3:7}
)
})
observeEvent(input$fity, {
newymax <- trunc(max(ydata())) + 1
newymin <- trunc(min(ydata()))
updateNumericInput(session, "ymax", value = newymax)
updateNumericInput(session, "ymin", value = newymin)}
)
observeEvent(input$yaxis, {
newymax <- trunc(max(ydata())) + 1
newymin <- trunc(min(ydata()))
updateNumericInput(session, "ymax", value = newymax)
updateNumericInput(session, "ymin", value = newymin)}
)
output$myplot <- renderPlot({
par(mar = c(4, 4, 0.1, 0.1))
plot(x = 1:5, y = ydata(), ylim = c(input$ymin, input$ymax))
})
}
shinyApp(ui = ui, server = server)
But this makes your 'zoom to fit' button redundant.

update values in numericInput R shiny

I have an app wherein users can input numeric values for certain fields (using numericInput()). Alternatively, they can choose to select values from a reference table (via a checkboxInput() field).
I'm able to code this behaviour in the script properly. But I also want that if the checkboxInput field is selected, the values displayed in the numericInput() get updated i.e. the default values or previously written values are overwritten.
In the screenshot, the numericInput fields are highlighted in yellow. The top field has a default value of 14 whereas the others are empty. I want that the if the "Copy reference values?" checkboxInput is selected, the copied values get displayed in the corresponding fields (k1 = 72.49 for "Flow Coef. for dP" etc.)
My code is as below:
fluidRow(
column(4,
numericInput(inputId = "Area",
label = tags$div(HTML(paste("rea (m", tags$sup(2), ")", sep = ""))),
min = 1, max = 100, step = 0.1, value = 14),
numericInput(inputId = "k1", label = "Flow coef. for dP", min = 1.0, max = 600.0, value = ""),
numericInput(inputId = "k2", label = "Flow exponent for dP" , min = 1.0, max = 20.0, value = "")
checkboxInput("copyVals", "Copy Reference Values?", value = FALSE)
)
You'll want to use an observeEvent and updateNumericInputs. Since you didn't provide a reproducible example here is a mockup:
library("shiny")
library("DT")
data <- data.frame(area = 18.61, k1 = 74.29, k2 = 1.44)
server <- function(input, output, session) {
# assuming your data is reactive, not static
data_reac <- reactive({
data
})
output$parm_tab <- renderDataTable({
datatable(data_reac())
})
# set the values if checked
observeEvent(input$copyVals == TRUE, {
c_data <- data_reac()
updateNumericInput(session, "area", value = c_data$area)
updateNumericInput(session, "k1", value = c_data$k1)
updateNumericInput(session, "k2", value = c_data$k2)
}, ignoreInit = TRUE)
}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
numericInput(inputId = "area", label = "Area", min = 1, max = 100, step = 0.1, value = 14),
numericInput(inputId = "k1", label = "Flow coef. for dP", min = 1.0, max = 600.0, value = ""),
numericInput(inputId = "k2", label = "Flow exponent for dP" , min = 1.0, max = 20.0, value = ""),
checkboxInput("copyVals", "Copy Reference Values?", value = FALSE)
)
, mainPanel(
dataTableOutput("parm_tab")
)
)
)
shinyApp(ui = ui, server = server)
Before
After

Shiny Slider Customized Values

I am trying to set custom values for shiny slider (1,5,10,15,20,25 and 30). I tried step but then the results either (0,5,10,15,20,25,30) or (1,6,11,16,21,26,31). Is there any way yo define custom values for slider?
Thanks!
plotpath <- "/Volumes/share-ites-1-$/Projects/Scientifica/Simulations_Scientifica"
ui <- fluidPage(
titlePanel("LandClim Simulations"),
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "temp",
label = "Temperature increase:",
value = 1, min = 1, max = 2,
step = 1, animate = TRUE ),
sliderInput(inputId = "prec",
label = "Precipitation change:",
value = 0, min = -2, max = 2,
step = 1, animate = TRUE ),
sliderInput(inputId = "decade",
label = "Time (decade):",
value = 1, min = 0, max = 30,
step = 5, animate = TRUE )
),
mainPanel(imageOutput("image"))
)
)
server <- function(input, output) {
output$image <- renderImage( deleteFile = FALSE, {
return(list(
src = paste(plotpath,"/Temp",input$temp,"Prec",input$prec,"Dec",input$decade,".png",sep = ""),
contentType = "image/png"))
} ) }
shinyApp(ui = ui, server = server)
The shinyWidgets package now solves this for you with a slider that allows custom values. Updated code for your third slider would look like this:
shinyWidgets::sliderTextInput(inputId = "decade",
label = "Time (decade):",
choices = c(1,5,10,15,20,25,30))
Although Shiny gives options to customize the slider Input,I do not think there is a way to to get output in the form (1,5,10...).This is because the difference between your 1st and 2nd point is 4 and thereafter it is 5 which will be inconsistent with the way step parameter works.Step can only generate numbers based on constant differences between slider inputs.
Depending on the need to have a slider, to have inputs with variable breaks you could use one of the other options, like
selectInput
https://shiny.rstudio.com/reference/shiny/latest/selectInput.html
or even checkboxInput
https://shiny.rstudio.com/reference/shiny/latest/checkboxInput.html
This can be easily done using sliderTextInput function in shiny. No need to add all this complex js function. Just a few lines of code will do the trick.Install the shinywidgets package which contains the sliderTextInput function. Do the following :
sliderTextInput("decade","Time (decade):,
choices = c(1,5,10,15,20,25,30),
selected = c(1,5,10,15,20,25,30),
animate = FALSE, grid = FALSE,
hide_min_max = FALSE, from_fixed = FALSE,
to_fixed = FALSE, from_min = NULL, from_max = NULL, to_min = NULL,
to_max = NULL, force_edges = FALSE, width = NULL, pre = NULL,
post = NULL, dragRange = TRUE)

RShiny reactive error

I am building a simple RShiny App that calculates sample size and power, but I keep getting this error message---
Warning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
I couldn't figure out how to fix it. This is my first time using RShiny. If anyone can help, I really appreciate that! Thanks a lot!
library(shiny)
ui <- fluidPage(
headerPanel("Power and Sample Size Calculator"),
fluidRow(column(12,
wellPanel(
helpText("Two proportions (equal sample size in each group) power/sample size analysis"),
selectInput (inputId = "choice",
label = " Please Choose What You Want To Calculate",
c("Power","Sample Size"),selected = NULL,
multiple = FALSE,
selectize = TRUE, width = NULL, size = NULL)
)),
column(4,
wellPanel(
conditionalPanel(
condition = "input$choice = Power",
numericInput (inputId = "tau",
label = "Effect Size",
value = "0.2",
min = 0, max =1),
numericInput (inputId = "n",
label = "Sample Size in Each Group",
value = "200",
min = 0,
max = 100000000),
sliderInput (inputId = "alpha",
label = "Significance Level ⍺= ",
value = "0.05",
min = 0.001, max = 0.10)),
conditionalPanel(
condition = "input$choice=Sample Size",
numericInput (inputId = "tau",
label = "Effect Size",
value = "0.2",
min = 0, max =1),
sliderInput (inputId = "alpha",
label = "Significance Level ⍺= ",
value = "0.05",
min = 0.001, max = 0.10),
numericInput (inputId = "beta",
label = "Power",
value = "0.8",
min = 0,
max = 1))
)
),
column(8,
wellPanel(
htmlOutput("Result")
))
))
server <- function(input, output) {
choice <- switch (input$choice,
"Power" = 1, "Sample Size" = 2)
output$Result <- renderUI({
if(choice==1){
final=reactive({pwr.2p.test(h = input$tau, n = input$n, sig.level = input$alpha, power = )
})
}
if(choice==2){
final=reactive({pwr.2p.test(h = input$tau, n = , sig.level = input$alpha, power = input$beta)
})}
HTML(final)
}
)
}
shinyApp(ui=ui, server=server)
I don't think it is required to have reactive for final. try this below.
it works for me, except for pwr.2p.test, looks like that is some function you are trying to use. Also, I did not understand why you had HTML(final), use of renderUishould generate html by default. Let me know how did it go. Good luck
server <- function(input, output) {
choice <- reactive({
switch(input$choice,"Power" = 1,"Sample Size" = 2)})
output$Result <- renderUI({
if (input$choice == 'Power') {
pwr.2p.test( h = input$tau,
n = input$n,
sig.level = input$alpha,
power = input$beta
)}
if (input$choice == 'Sample Size') {
pwr.2p.test( h = input$tau,
n = ,
sig.level = input$alpha,
power = input$beta
)}
})
}

Resources