Is there a way to only allow dragging a sliderInput? - r

I would like to fix the range in a shiny sliderInput such that it may only be dragged left or right, keeping the same range always. In the example below, the range is always kept to 10 but any range of 10 may be selected, e.g. 71-81 etc. Is it possible?
library(shiny)
ui <- fluidPage(
sliderInput(
inputId = "foo",
label = "Select Range",
min = 0,
max = 100,
value = c(50, 60),
step = 1,
dragRange = T
))
shinyApp(ui = ui, server = function(input, output) {})

Perhaps you are looking for this
library(shiny)
ui <- fluidPage(
sliderInput(
inputId = "foo",
label = "Select Range",
min = 0,
max = 100,
value = c(50, 60),
step = 1,
dragRange = T
))
server = function(input, output,session) {
observeEvent(input$foo[1], {
if (input$foo[1]<=90) mnval <- input$foo[1]
else mnval = 90
mxval = input$foo[1] + 10
updateSliderInput(session, "foo", min =0,max=100, value = c(mnval,mxval))
})
}
shinyApp(ui = ui, server = server)

Related

Calculating sum in Shiny

I'm trying to create a shiny app as a practice planner where users can select which drills they are going to do and how long they will do each drill and the app then shows them the total meters covered for the whole practice. Now I'm trying to calculate the total values of meters covered during a session based on the drills selected and the number of minutes selected for each drill. However my total is always equal to 0 even though it works for calculating each drill separately. Could someone help me figure out what I'm doing wrong please. Below is my code with sample data.
library(shiny)
library(dplyr)
# MyData <- read.csv("/Users/sonamoravcikova/Desktop/ShinyTest/ForShiny1.csv")
MyData <- structure(list(Drill = c("GP Warm Up", "5v2 Rondo", "11v11", "10v6 Drop
Behind Ball"), PlayerLoadPerMinute = c(7.72949670665213, 6.49382926701571,
9.67483408668731, 5.86770863636364), MetersPerMinute = c(69.9524820610687,
45.823744973822, 95.9405092879257, 58.185375), class = "data.frame", row.names
= c(NA, -4L)))
# Define UI ----
ui <- fluidPage(
titlePanel("Practice Planner"),
sidebarLayout(
sidebarPanel(
#Select number of drills
numericInput("num", h3("Number of Drills"), value = 1),
textOutput("MpM_Total")
),
mainPanel(
#Show boxes for the number of drill selected and select drill type
selectInput("DrillName1",
label = "Choose a Drill:",
choices = unique(MyData$Drill),
selected = NULL,
multiple = FALSE),
sliderInput("slider1",
label = h3("Slider"),
min = 0,
max = 60,
value = 0),
textOutput("MpM1"),
br(),
conditionalPanel(
condition = "input.num > '1'",
selectInput("DrillName2",
label = "Choose a Drill:",
choices = unique(MyData$Drill),
selected = NULL,
multiple = FALSE),
sliderInput("slider2",
label = h3("Slider"),
min = 0,
max = 60,
value = 0),
textOutput("MpM2")),
br(),
conditionalPanel(
condition = "input.num > '2'",
selectInput("DrillName3",
label = "Choose a Drill:",
choices = unique(MyData$Drill),
selected = NULL,
multiple = FALSE),
sliderInput("slider3",
label = h3("Slider"),
min = 0,
max = 60,
value = 0),
textOutput("MpM3"))
)
)
)
# Define server logic ----
server <- function(input, output, session) {
#Calculate number of meters covered
lapply(1:10, function(x) {
MetersPerMin <- reactive({
chosendrill <- input[[paste0("DrillName",x)]]
MpM <- MyData %>%
distinct(MetersPerMinute, .keep_all = T)
MpM_text <- (MpM$MetersPerMinute[MpM$Drill == chosendrill]) * (input[[paste0("slider",x)]])
})
output[[paste0("MpM", x)]] <- renderText({
paste0("Meters covered: ", MetersPerMin())
})
MpM_Sum <- reactive({
sum(MetersPerMin())
})
output$MpM_Total <- renderText({
paste("Total Meters Covered", MpM_Sum())
})
})
}
# Create Shiny app ----
shinyApp(ui = ui, server = server)
library(shiny)
library(dplyr)
MyData <- data.frame(Drill = c('GP Warm Up', '5v2 Rondo', '11v11', '10v6 Drop Behind Ball'),
PlayerLoadPerMinute = c(7.72949670665213, 6.49382926701571, 9.67483408668731, 5.86770863636364),
MetersPerMinute = c(69.9524820610687, 45.823744973822, 95.9405092879257, 58.185375))
MpM <- MyData %>%
distinct(MetersPerMinute, .keep_all = T)
# Define UI ----
ui <- fluidPage(
titlePanel('Practice Planner'),
sidebarLayout(
sidebarPanel(
#Select number of drills
numericInput('num', h3('Number of Drills'), value = 1),
textOutput('MpM_Total')
),
mainPanel(
#Show boxes for the number of drill selected and select drill type
selectInput('DrillName1',
label = 'Choose a Drill:',
choices = unique(MyData$Drill),
selected = NULL,
multiple = FALSE),
sliderInput('slider1',
label = h3('Slider'),
min = 0,
max = 60,
value = 0),
textOutput('MpM1'),
br(),
conditionalPanel(
condition = 'input.num > "1"',
selectInput('DrillName2',
label = 'Choose a Drill:',
choices = unique(MyData$Drill),
selected = NULL,
multiple = FALSE),
sliderInput('slider2',
label = h3('Slider'),
min = 0,
max = 60,
value = 0),
textOutput('MpM2')
),
br(),
conditionalPanel(
condition = 'input.num > "2"',
selectInput('DrillName3',
label = 'Choose a Drill:',
choices = unique(MyData$Drill),
selected = NULL,
multiple = FALSE),
sliderInput('slider3',
label = h3('Slider'),
min = 0,
max = 60,
value = 0),
textOutput('MpM3')
)
)
)
)
# Define server logic ----
server <- function(input, output, session) {
MetersPerMin <- reactive({
idx <- input$num
if (idx < 1) {
idx <- 1
} else if (idx > 3) {
idx <- 3
}
mpms <- sapply(1:idx, function(x) {
chosendrill <- input[[ paste0('DrillName', x) ]]
mpm <- (MpM$MetersPerMinute[ MpM$Drill == chosendrill ]) * (input[[ paste0('slider', x) ]])
output[[ paste0('MpM', x) ]] <- renderText(paste0('Meters covered: ', mpm))
mpm
})
mpms
})
output$MpM_Total <- renderText({
paste('Total Meters Covered', sum(MetersPerMin()))
})
}
# Create Shiny app ----
shinyApp(ui = ui, server = server)

Can you have two interdependent inputs in R Shiny that rely on other inputs?

I'm looking at having two sliders that should update together, based on some function. For example, one slider is the square root of the other. I want to be able to change either slider and for the other one to update reactively.
The following does work:
library(shiny)
server = function(input, output) {
f = reactive(function(x) x^2)
finv =reactive(function(x) sqrt(x))
output$x <- renderUI({
slider_s.value <- input$s
default.slider_x <- if (is.null(slider_s.value)) 1 else f()(slider_s.value)
sliderInput("x", "Select x:",
min = 0, max=100,
value = default.slider_x, step = 0.01,
animate = animationOptions(interval = 600, loop = TRUE))
})
output$s <- renderUI({
slider_x.value <- input$x
default.slider_s <- if (is.null(slider_x.value)) finv()(1) else finv()(slider_x.value)
sliderInput("s", "Select s:",
min = 0, max=10,
value = default.slider_s, step = 0.01,
animate = animationOptions(interval = 600, loop = TRUE))
})
}
ui = fluidPage(
titlePanel("One Way Reactive Slider"),
fluidRow(
column(3,
wellPanel(
h4("Slider Inputs"),
uiOutput('s'),
uiOutput('x')
))
)
)
shinyApp(ui = ui, server = server)
However, this doesn't.
library(shiny)
server = function(input, output) {
g = reactive(function(x) x^2 - input$slider)
ginv =reactive(function(x) sqrt(x+ input$slider))
output$slider <- renderUI({
sliderInput("slider", "Slider input:",
min = 1, max = 100, value = 2)
})
output$x <- renderUI({
slider_s.value <- input$s
default.slider_x <- if (is.null(slider_s.value)) 1 else g()(slider_s.value)
sliderInput("x", "Select x:",
min = 0, max=100,
value = default.slider_x, step = 0.01,
animate = animationOptions(interval = 600, loop = TRUE))
})
output$s <- renderUI({
slider_x.value <- input$x
default.slider_s <- if (is.null(slider_x.value)) ginv()(1) else ginv()(slider_x.value)
sliderInput("s", "Select s:",
min = 0, max=10,
value = default.slider_s, step = 0.01,
animate = animationOptions(interval = 600, loop = TRUE))
})
}
ui = fluidPage(
titlePanel("One Way Reactive Slider"),
fluidRow(
column(3,
wellPanel(
h4("Slider Inputs"),
uiOutput('slider'),
uiOutput('s'),
uiOutput('x')
))
)
)
shinyApp(ui = ui, server = server)
It messes up when the "Slider Input" is changed. Is there some way that I can get round this? I've seen other posts on here about constraining sliders but none seem to rely on other inputs like this.
Note that I want x = g(s) and s = ginv(x) which should be okay since g and ginv are inverses of each other!
Some changes are required in output$x <- RenderUI code block to fix the slider values flickering issue.
output$x <- renderUI({
slider_slider.value <- input$slider
default.slider_x <- if (is.null(slider_slider.value)) 1 else g()(slider_slider.value)
sliderInput("x", "Select x:",
min = 0, max=100,
value = default.slider_x, step = 0.01,
animate = animationOptions(interval = 600, loop = TRUE))
})

selecting slider to display in r shinyapps

I am trying to use selectInput in shiny aps to create a menu that changes the displayed slider.
ui <- fluidPage (
selectInput (inputId = "sat_act", "Choose your test:",
c("SAT" = "SATscore", "ACT" = "ACTscore")
sliderInput (inputId = "SATscore",
label = "Select your SAT score", step = 10,
value = 1000, min = 400, max = 1600),
sliderInput (inputId = "ACTscore",
label = "Select your ACT score",
value = 18, min = 1, max = 36)
plotOutput (outputId = "graph")
)
server <- function(input,output){}
shinyApp(ui = ui, server = server)
Currently, my code displays boy sliders and has no drop down menu. I am uncertain how to implement this and have not found an example online. Any help would be appreciated.
You could use renderUI().
On server side you evaluate your sat_act input and depending of the choice you render the new ui element:
output$score <- renderUI({
if(input$sat_act == "SATscore"){
return(...)
}
})
Full app:
library(shiny)
ui <- fluidPage (
selectInput (inputId = "sat_act", "Choose your test:",
c("SAT" = "SATscore", "ACT" = "ACTscore")),
uiOutput("score"),
plotOutput (outputId = "graph")
)
server <- function(input,output){
output$score <- renderUI({
if(input$sat_act == "SATscore"){
return(
sliderInput (inputId = "SATscore",
label = "Select your SAT score", step = 10,
value = 1000, min = 400, max = 1600)
)
}else{
return(
sliderInput (inputId = "ACTscore",
label = "Select your ACT score",
value = 18, min = 1, max = 36)
)
}
})
}
shinyApp(ui = ui, server = server)
Create an UI
library(shiny)
ui <- fluidPage (
selectInput(inputId = "sat_act", "Choose your test:",
c("SAT" = "SATscore", "ACT" = "ACTscore")),
uiOutput('slider'),
plotOutput (outputId = "graph")
)
server <- function(input,output){
output$slider = renderUI({
if (input$sat_act == 'SATscore') {
sliderInput(inputId = "SATscore",
label = "Select your SAT score", step = 10,
value = 1000, min = 400, max = 1600)
} else {
sliderInput(inputId = "ACTscore",
label = "Select your ACT score",
value = 18, min = 1, max = 36)
}
})
}
shinyApp(ui = ui, server = server)

Calculate in Shinyapps

I want to calculate some values and return the values to my shiny app:
ui <- fluidPage(
sidebarLayout(
sidebarPanel(numericInput(inputId = "ME",
label = "Maternal effect:",
min = -1,
max = 1,
value = 0.5),
numericInput(inputId = "CE",
label = "Child effect:",
min = -1,
max = 1,
value = 0.5)
),
mainPanel(h3(textOutput("Power"))
)
)
)
server <- function(input, output) {
bzc <- sqrt(abs(input$CE)) * sign(input$CE)
bzm <- sqrt(abs(input$ME)) * sign(input$ME)
results <- bzc * bzm
output$Power <- renderPrint({results
})
}
shinyApp(ui = ui, server = server)
This doesnt apprear to work. Any tips on how to calculate in the shiny app?
The error-messages arise, because you have input-objects outside of the render-functions. If you want to calculate something, which you want to reuse in multiple plots, then use a reactive or observe-function.
For all other cases it is enough add the code for bzc, bzm and result inside the render-functions:
ui <- fluidPage(
sidebarLayout(
sidebarPanel(numericInput(inputId = "ME",
label = "Maternal effect:",
min = -1,
max = 1,
value = 0.5),
numericInput(inputId = "CE",
label = "Child effect:",
min = -1,
max = 1,
value = 0.5)
),
mainPanel(h3(textOutput("Power"))
)
)
)
server <- function(input, output) {
output$Power <- renderPrint({
bzc <- sqrt(abs(input$CE)) * sign(input$CE)
bzm <- sqrt(abs(input$ME)) * sign(input$ME)
results <- bzc * bzm
results
})
}
shinyApp(ui = ui, server = server)

Update sliderInput in Shiny reactively

I am trying to change the values from a sliderInput dynamically. The difficulty now is that I want to change from a sliderInput with one value, to a sliderInput with a range, which seems not to work.
The first actionbutton in the code below works, while the second does not what it is intended to do.
Is the only possibility to switch to an uiOutput element?
Code
library(shiny)
app <- shinyApp(
ui = bootstrapPage(
sliderInput("sld1", min = 0, max = 10, label = "y1", value = 5),
actionButton("acb1", "Change Value"),
actionButton("acb2", "Change Value to Range")
),
server = function(input, output, session) {
observeEvent(input$acb1, {
updateSliderInput(session, "sld1", value = 2)
})
observeEvent(input$acb2, {
updateSliderInput(session, "sld1", value = c(2,7))
})
})
runApp(app)
You can maybe add the slider dynamically using renderUI
#rm(list = ls())
library(shiny)
app <- shinyApp(
ui = bootstrapPage(
uiOutput("myList"),
actionButton("acb1", "Change Value"),
actionButton("acb2", "Change Value to Range")
),
server = function(input, output, session) {
slidertype <- reactiveValues()
slidertype$type <- "default"
observeEvent(input$acb1,{slidertype$type <- "normal"})
observeEvent(input$acb2, {slidertype$type <- "range"})
output$myList <- renderUI({
if(slidertype$type == "normal"){
sliderInput("sld1", min = 0, max = 10, label = "y1", value = 2)
}
else if(slidertype$type == "range"){
sliderInput("sld1", min = 0, max = 10, label = "y1", value = c(2,7))
}
else{
sliderInput("sld1", min = 0, max = 10, label = "y1", value = 5)
}
})
})
runApp(app)

Resources