R Shiny: actionButton to generate random value from input values and render plot - r

I have made a simple shiny app that generates a plot of the x and y data from an individual group within the data which the users can choose from. The app subsets the larger dataframe and produces the graph for only the chosen individual. I would also like to include and actionButton which chooses an individual from within the dataset at random and plots that every time the button is pushed.
library(shiny)
library(tidyverse)
# Create example data frame
Data <- data.frame(Indiv = c(rep(1,10),
rep(2,10),
rep(3,10),
rep(4,10),
rep(5,10),
rep(6,10)),
varX = c(runif(10, min = 1, max = 10),
runif(10, min = 1, max = 10),
runif(10, min = 1, max = 10),
runif(10, min = 1, max = 10),
runif(10, min = 1, max = 10),
runif(10, min = 1, max = 10)),
varY = c(runif(10, min = 1, max = 1),
runif(10, min = 1, max = 5),
runif(10, min = 1, max = 10),
runif(10, min = 1, max = 15),
runif(10, min = 1, max = 20),
runif(10, min = 1, max = 25))
)
###### Shiny App #######
# User interface for shiny app
ui <- fluidPage(
titlePanel("Random Select Button"), # page title
sidebarLayout(
# Sidebar panel
sidebarPanel(
# input for which TagID to display in plot
actionButton("do", "Plot Random Indiv"),
selectInput(inputId = "ID",
label = "Individual ID",
choices = levels(factor(Data$Indiv)),
selected = NULL, # choose no individuals by default
multiple = FALSE # allow for multiple options
),
p("Choose an invidual, or push the button to randomly choose an individual."),
),
# Main Panel
mainPanel(
plotOutput("IndivPlot"), # name of plot object
),
)
)
# Server
server <- function(input, output) {
# Plot
output$IndivPlot <- renderPlot({ # make a live adjustable plot
### Filter to only include selected Individual
Data <- Data[Data$Indiv %in% input$ID,]
# Create plot
p = ggplot(data=Data, aes(x=varX, y=varY))+
geom_line()+
expand_limits(y=c(1,30), x = c(1,10))+
scale_y_continuous(breaks=seq(1,30,5), labels=seq(1,30,5))+
scale_x_continuous(breaks = seq(1,10,1), labels = seq(1,10,1))+
labs(x = "My X", y = "My Y")
print(p)
})
}
shinyApp(ui = ui, server = server)
I can't figure out how to get the action button to randomly choose and individual ID number and cause the plot to render. Right now, the button exists on the UI but doesn't do anything.

You may create a reactive ID which will be dynamic. It will be updated when the ID is selected from the dropdown as well as when the action button is pressed to generate random ID.
The plot will be updated based on the ID.
library(shiny)
library(tidyverse)
###### Shiny App #######
# User interface for shiny app
ui <- fluidPage(
titlePanel("Random Select Button"), # page title
sidebarLayout(
# Sidebar panel
sidebarPanel(
# input for which TagID to display in plot
actionButton("do", "Plot Random Indiv"),
selectInput(inputId = "ID",
label = "Individual ID",
choices = levels(factor(Data$Indiv)),
selected = NULL, # choose no individuals by default
multiple = FALSE # allow for multiple options
),
p("Choose an invidual, or push the button to randomly choose an individual."),
),
# Main Panel
mainPanel(
plotOutput("IndivPlot"), # name of plot object
),
)
)
# Server
server <- function(input, output, session) {
#To save dynamic ID
rv <- reactiveValues()
observe({
#ID selected from the dropdown manually
rv$ID <- input$ID
})
# Plot
output$IndivPlot <- renderPlot({ # make a live adjustable plot
### Filter to only include selected Individual
Data <- Data[Data$Indiv %in% rv$ID,]
# Create plot
p = ggplot(data=Data, aes(x=varX, y=varY))+
geom_line()+
expand_limits(y=c(1,30), x = c(1,10))+
scale_y_continuous(breaks=seq(1,30,5), labels=seq(1,30,5))+
scale_x_continuous(breaks = seq(1,10,1), labels = seq(1,10,1))+
labs(x = "My X", y = "My Y")
print(p)
})
#On action button click
observeEvent(input$do, {
#Select a random ID
rv$ID <- sample(unique(Data$Indiv), 1)
#Update the value of dropdown with random ID selected
updateSelectInput(session, inputId = "ID",
label = "Individual ID",
choices = levels(factor(Data$Indiv)),
selected = rv$ID)
})
}
shinyApp(ui = ui, server = server)

Related

how to update a dataset in R shiny

Can I get help on how to get the below code to work? I am looking to update the numbers in
dataExample <- getDataset(n1 = c(20),n2 = c(20), means1 = c(18), means2 = c(9),stds1 = c(14), stds2 = c(14))
based on input values and then generate the plot whenever I apply changes but not sure how to do it. I read it somewhere it says need to use reactive or observe but I am not sure how to modify the code?
library(shiny)
library(plyr)
library(rmarkdown)
library(rpact)
design <- getDesignGroupSequential(kMax = 2, alpha = 0.05, informationRates = c(0.5, 1), typeOfDesign = "WT", deltaWT = 0.5)
ui <- fluidPage(
titlePanel("Efficacy Monitoring Using Conditional Power"),
sidebarLayout(
sidebarPanel(
numericInput('nn1', 'Number of Subjects at Current stage (Active)', 20, min = 1, max = 100),
numericInput('nn2', 'Number of Subjects at Current stage (Control)', 20, min = 1, max = 100),
textInput('Mean1', 'Mean1',"18"),
textInput('Mean2', 'Mean2',"9"),
textInput('SD1', 'SD1',"14"),
textInput('SD2', 'SD2',"14"),
textInput('nPlanned', 'Additional Numbers Planned',"40"),
submitButton(text = 'Apply Changes')
),
# Main panel for displaying outputs ----
mainPanel(plotOutput("plot2")
)
)
)
server <- function(input,output){
dataExample <- getDataset(
n1 = c(20),
n2 = c(20),
means1 = c(18),
means2 = c(9),
stds1 = c(14),
stds2 = c(14)
)
stageResults <- getStageResults(design, dataExample,thetaH0 = 0)
output$plot2<-renderPlot(
plot(stageResults, nPlanned = c(as.numeric(input$nPlanned)), thetaRange = c(0, 20))
)
}
# Run the app ----
shinyApp(ui, server)
Use a reactive function and put the input values
library(shiny)
library(plyr)
library(rmarkdown)
library(rpact)
design <- getDesignGroupSequential(kMax = 2, alpha = 0.05, informationRates = c(0.5, 1), typeOfDesign = "WT", deltaWT = 0.5)
ui <- fluidPage(
titlePanel("Efficacy Monitoring Using Conditional Power"),
sidebarLayout(
sidebarPanel(
numericInput('nn1', 'Number of Subjects at Current stage (Active)', 20, min = 1, max = 100),
numericInput('nn2', 'Number of Subjects at Current stage (Control)', 20, min = 1, max = 100),
# WHY THE CHOICE OF textInput instead of numericInput ?
textInput('Mean1', 'Mean1',"18"),
textInput('Mean2', 'Mean2',"9"),
textInput('SD1', 'SD1',"14"),
textInput('SD2', 'SD2',"14"),
textInput('nPlanned', 'Additional Numbers Planned',"40"),
submitButton(text = 'Apply Changes')
),
# Main panel for displaying outputs ----
mainPanel(plotOutput("plot2")
)
)
)
server <- function(input,output){
# Use the input values in a reactive function
dataExample <- reactive({
getDataset(
n1 = input$nn1,
n2 = input$nn2,
means1 = as.numeric(input$Mean1),
means2 = as.numeric(input$Mean2),
stds1 = as.numeric(input$SD1),
stds2 = as.numeric(input$SD2)
)
})
output$plot2<-renderPlot({
stageResults <- getStageResults(design, dataExample(), thetaH0 = 0)
plot(stageResults, nPlanned = c(as.numeric(input$nPlanned)), thetaRange = c(0, 20))
})
}
# Run the app ----
shinyApp(ui, server)

R Shiny Reactive Plot from List of Lists

I'm building a basic R Shiny app, and have a list that contains individual lists, each storing a dataframe and a value. I've included sample data to demonstrate my list of lists. Within my app I am trying to have one select option (a dropdown menu that says "List 1", List 2", etc) and then have the main panel in the app display a boxplot of the dataframe (x and y) and a text output of the value stored in the list that was selected.
I'm having trouble with the ability to make the outputs (both plot and text) reactive to the input and display data from the selected list.
I've put my code of what I have so far below.
## Example Data
list_a <- list(df = data.frame(x = rnorm(n = 10, mean = 5, sd = 2),
y = rnorm(n = 10, mean = 7, sd = 3)),
value = "a")
list_b <- list(df = data.frame(x = rnorm(n = 10, mean = 20, sd = 5),
y = rnorm(n = 10, mean = 13, sd = 7)),
value = "b")
list_c <- list(df = data.frame(x = rnorm(n = 10, mean = 12, sd = 4),
y = rnorm(n = 10, mean = 10, sd = 4)),
value = "c")
mylist <- list(list_a, list_b, list_c)
## Packages
library(tidyverse)
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Shiny App"),
## Panel with selectInput dropdown and output options
pageWithSidebar(
headerPanel('Data'),
sidebarPanel(
selectInput('data', 'Dataset',
choices = c("1" = list_a, "2" = list_b, "3" = list_c)),
),
mainPanel(
plotOutput('plot1'),
textOutput('text1')
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
## Boxplot with 'DF' from selected list
output$plot1 <- renderPlot({
reactivedata <- boxplot(input$data)
boxplot(reactivedata$df)
})
## Text output from 'value' stored in list
output$text1 <- renderText({
reactivetext <- print(input$data)
print(reactivetext$value)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Main issue with your code that you used your raw lists for the choices argument. Additionally I added a reactive to pick the right list according to the user's input:
set.seed(123)
library(tidyverse)
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("Shiny App"),
## Panel with selectInput dropdown and output options
pageWithSidebar(
headerPanel("Data"),
sidebarPanel(
selectInput("data", "Dataset",
choices = c("list_a" = 1, "list_b" = 2, "list_c" = 3)
),
),
mainPanel(
plotOutput("plot1"),
textOutput("text1")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {
reactivedata <- reactive({
mylist[[as.integer(input$data)]]
})
## Boxplot with 'DF' from selected list
output$plot1 <- renderPlot({
boxplot(reactivedata()$df)
})
## Text output from 'value' stored in list
output$text1 <- renderText({
print(reactivedata()$value)
})
}
# Run the application
shinyApp(ui = ui, server = server)
#>
#> Listening on http://127.0.0.1:4502
#> [1] "a"

Why am I getting 'server not found' error in my shiny app?

I'm trying to learn shiny on my own and it's been very fun so far. I'm trying to plot a singular point on a graph with both inputs coming from the user. I am getting a "Error in shinyApp(ui = ui, server = server) : object 'server' not found". Here's my code:
ui <- fluidPage(
titlePanel("Title"),
sidebarPanel(
sliderInput(inputId ="x1", 'I', min = 4, max = 12, value = 4),
sliderInput(inputId = "y1", 'Y', min = 0, max = 10, value = 1)),
plotOutput("Scale")
)
server() <- function(input, output){
output$Scale <- renderPlot({
ggplot(aes_string(x = input$x1, y = input$y1))+
geom_point() })
}
shinyApp(ui = ui, server = server)
Here is a complete working example, I hope this will help.
The slider inputs will provide numerical information for your plot. This might be easier to conceptualize if placed in a data frame (see below).
The aes aesthetic mapping provides information on x and y axis for your plot, and uses data to indicate dataset to use for plot.
Finally, added limits to appreciate the point moving around the graph with slider changes (otherwise, the axis will automatically rescale).
Lots more you can learn on ggplot2 here:
https://ggplot2.tidyverse.org/
library(ggplot2)
library(shiny)
ui <- fluidPage(
titlePanel("Title"),
sidebarPanel(
sliderInput(inputId ="x1", 'I', min = 4, max = 12, value = 4),
sliderInput(inputId = "y1", 'Y', min = 0, max = 10, value = 1)),
plotOutput("Scale")
)
server <- function(input, output){
output$Scale <- renderPlot({
my_data <- data.frame(x = input$x1, y = input$y1)
ggplot(aes(x = x, y = y), data = my_data)+
geom_point() +
xlim(4, 12) +
ylim(0, 10)
})
}
shinyApp(ui = ui, server = server)

Dependent observeEvents cause problems in complex applications

I prepared rather simple shiny application which resembles the problem in my much more complex application.
The three necessary components of my application are:
The number, i.e. year, can be changed in two different ways: by 1) adding a value in the textInput or 2) by clicking the action button
When the year is changed by the actionButtion, it must automatically change current value in the textInput box
When the year is changed by the textInput, reactive value for the
action button must reset to zero.
I have two observeEvents which both target two reactive values. The problem is, if I click the actionButton several times too quickly, this creates a loop of switching between those two events.
Is there any efficient tool available in Shiny which help in such situations? E.g. to prevent users to click on the button prior the execution of task.
# import libraries
library(shiny)
library(ggplot2)
library(dplyr)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput("ui_year"),
uiOutput("ui_plus")
),
mainPanel(
plotOutput("plot1")
)
)))
server <- shinyServer(function(input, output) {
# Generate random data
data <- data.frame(
year = seq(1900, 2000),
value = runif(n = 101, min = -3, max = 3)
)
# Define two reactive values: add and year
rv <- reactiveValues()
rv$add <- 0
rv$year <- 2000
# render actionButton
output$ui_plus <- renderUI({
actionButton(inputId = "add",
label = paste0(""),
icon = icon("plus"))
})
# render textInput
output$ui_year <- renderUI({
textInput(inputId = "year_1", label = NULL,
value = eval(parse( text = rv$year)),
width = "100%",
placeholder = NULL)
})
# Define two observe events, based on A) action button and B) textInput
observeEvent(input$year_1, {
rv$year <- input$year_1
rv$add <- 0
})
observeEvent(input$add, {
rv$add <- rv$add + 1
rv$year <- as.numeric(rv$year) + 1
})
# Render output
output$plot1 <- renderPlot({
sumValue <- as.numeric(rv$year) + as.numeric(rv$add)
ggplot(data, aes(x = year, y = value)) + geom_line()+ annotate("text", x = -Inf, y = Inf, hjust = -0.2, vjust = 1, label = sumValue )
})
})
shinyApp(ui = ui, server = server)

Applying selecting dataset and filtering in R shiny

I've this problem. I'm starting to learn shiny and I can't figure out how to use a filter on a dataset derived from another shiny selector.
In this particular case I would like to have one filter that works for any dataset that is selected at the first step.
I want to filter the dataset according to the column C, in particular I want to visualize only the rows with C > 1.
I'll report the code:
library(shiny)
set.seed(1)
rock <- data.frame(unif = runif(100, -1, 1),
norm = rnorm(100, 0, 2),
pois = rpois(100, 1))
paper <- data.frame(unif = runif(100, -2, 2),
norm = rnorm(100, 0, 4),
pois = rpois(100, 2))
scissor <- data.frame(unif = runif(100, -3, 3),
norm = rnorm(100, 0, 6),
pois = rpois(100, 3))
# Define UI for dataset viewer application
ui <- shinyUI(pageWithSidebar(
# Application title
headerPanel("Shiny Text"),
# Sidebar with controls to select a dataset and specify the number
# of observations to view
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "paper", "scissor")),
sliderInput("range", "Range:",
min = 0, max = 10,
value = c(0.5,5)),
numericInput("obs", "Number of observations to view:", 20)
),
# Show an HTML table with the requested
# number of observations
mainPanel(
tableOutput("view")
)
))
# Define server logic required to summarize and view the selected dataset
server <- shinyServer(function(input, output) {
# Return the requested dataset
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"paper" = paper,
"scissor" = scissor)
})
#Creating a data frame based on inputs
####?????####
# Show the first "n" observations
output$view <- renderTable({
head(datasetInput(), n = input$obs)
})
})
shinyApp(ui = ui, server = server)
My problem is what to put instead of ####?????#### in the server part.
I hope you can help me.
Something like this?
library(shiny)
set.seed(1)
rock <- data.frame(unif = runif(100, -1, 1),
norm = rnorm(100, 0, 2),
pois = rpois(100, 1))
paper <- data.frame(unif = runif(100, -2, 2),
norm = rnorm(100, 0, 4),
pois = rpois(100, 2))
scissor <- data.frame(unif = runif(100, -3, 3),
norm = rnorm(100, 0, 6),
pois = rpois(100, 3))
# Define UI for dataset viewer application
ui <- shinyUI(pageWithSidebar(
# Application title
headerPanel("Shiny Text"),
# Sidebar with controls to select a dataset and specify the number
# of observations to view
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "paper", "scissor")),
sliderInput("range", "Range:",
min = 0, max = 10,
value = c(0.5,5)),
numericInput("obs", "Number of observations to view:", 20)
),
# Show an HTML table with the requested
# number of observations
mainPanel(
tableOutput("view")
)
))
# Define server logic required to summarize and view the selected dataset
server <- shinyServer(function(input, output) {
# Return the requested dataset
datasetInput <- reactive({
switch(input$dataset,
"rock" = rock,
"paper" = paper,
"scissor" = scissor)
})
#Creating a data frame based on inputs
seconddata <- reactive({
d <- datasetInput()
d[d[,3] >= input$range[1] & d[,3] <= input$range[2],]
})
####?????####
# Show the first "n" observations
output$view <- renderTable({
head(seconddata(), n = input$obs)
})
})
shinyApp(ui = ui, server = server)

Resources