I am working on an Interactive Shiny App. To display the next plot on a mouse click, I have to track the very previous value of a variable. But when I click on the plot All the variables reset. Can you please suggest me a way to stop a variable from resetting on every iteration.
For example:
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
actionButton("Reset", label="Reset Graph")
),
mainPanel(
plotOutput("graph", width = "100%", click = "plot_click"),
verbatimTextOutput("click_info")
)
)
)
)
server <- shinyServer(function(input, output, session) {
level <- "Value1"
observeEvent(input$Reset,{
output$graph <- renderPlot({ plot(1, 1) }) }, ignoreNULL = F)
print(level)
# interaction click in graph
observe({
if(is.null(input$plot_click$x)) return(NULL)
x <- sample(20:30,1,F)
level <- "Value2"
isolate({
output$graph <- renderPlot({
draw.single.venn(x)
})
})
})
})
shinyApp(ui=ui,server=server)
I have changed the level variable to "Value2". But on next iteration, it again turns to "Value1" due to the first line of code. Can you help me to remain it as "Value2"?
You can define it as a reactive value:
server <- shinyServer(function(input, output, session) {
level_init <- reactiveValues(level="Value1")
level_react <- reactive({
level_init$level <- "Value2"
})
print(isolate(level_init$level))
observeEvent(input$Reset,{
output$graph <- renderPlot({ plot(1, 1) }) }, ignoreNULL = F)
# interaction click in graph
observe({
if(is.null(input$plot_click$x)) return(NULL)
x <- sample(20:30,1,F)
level_react()
print(level_init$level)
isolate({
output$graph <- renderPlot({
draw.single.venn(x)
})
})
})
})
shinyApp(ui=ui,server=server)
Related
I have a code as follows and I want to add a Save button to points that are brushed. Many thanks in advance.
library(shiny)
ui <- basicPage(
plotOutput("plot1", brush = "plot_brush"),
verbatimTextOutput("info")
)
server <- function(input, output) {
x <- NULL
output$plot1 <- renderPlot({
plot(mtcars$wt, mtcars$mpg)
})
output$info <- renderPrint({
x <<- brushedPoints(mtcars, input$plot_brush, xvar = "wt", yvar = "mpg")
x
})
}
shinyApp(ui, server)
Add an actionButton when clicked saves the brushed dataframe. Also made output of brushedPoints as reactive so we can use it multiple times in the code.
library(shiny)
ui <- basicPage(
plotOutput("plot1", brush = "plot_brush"),
verbatimTextOutput("info"),
actionButton("save", "Save")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
plot(mtcars$wt, mtcars$mpg)
})
data <- reactive({
brushedPoints(mtcars, input$plot_brush, xvar = "wt", yvar = "mpg")
})
output$info <- renderPrint({data()})
observeEvent(input$save, {
write.csv(data(), 'brushed_data.csv', row.names = FALSE)
})
}
shinyApp(ui, server)
Here is a sample code to generate a plot upon clicking the actionButton.
shinyApp(
shinyUI(fluidPage(
inputPanel(
numericInput("n", "n", 10),
actionButton("update", "Update")
),
plotOutput("plot")
)),
shinyServer(function(input, output) {
values <- reactiveValues()
values$data <- c()
obs <- observe({
input$update
isolate({ values$data <- c(values$data, runif(as.numeric(input$n), -10, 10)) })
}, suspended=TRUE)
obs2 <- observe({
if (input$update > 0) obs$resume()
})
output$plot <- renderPlot({
dat <- values$data
hist(dat)
})
})
)
I would like to display a default plot which is in www/test.png to appear when the application is launched. And then change the plot after clicking the actionButton as per the user input.
First, I create a simple plot, export it as an image (manually, not in code) and name it Rplot.png (save it where you want):
plot(mtcars$mpg)
Then, in the shiny app, we have to distinguish two situations :
when the app starts, no button is clicked yet, we render the image with renderImage
when we click on the button, we replace renderImage with renderPlot and render an interactive plot
This means that we must use uiOutput in ui part so that we can choose the output to be an image or a plot according to the situation.
Here's an example (I didn't adapt your code but it should not be too difficult):
library(shiny)
# determine your path to image here (you should use the package "here" to do so)
ui <- fluidPage(
selectInput("choice", "Choose", choices = names(mtcars)),
actionButton("run", "Run"),
uiOutput("some_ui")
)
server <- function(input, output, session) {
### "Static" part: no click on actionButton yet
output$some_ui <- renderUI({
imageOutput("image_plot")
})
output$image_plot <- renderImage({
list(src = "Rplot.png",
contentType = 'image/png')
}, deleteFile = FALSE) # Do not forget this option
### Click on actionButton
observeEvent(input$run, {
output$some_ui <- renderUI({
plotOutput("dynamic_plot")
})
output$dynamic_plot <- renderPlot({
plot(mtcars[[input$choice]])
})
})
}
shinyApp(ui, server)
The key is to use renderUI, so you can either show an image or a R plot. This should do what you desire:
shinyApp(
shinyUI(fluidPage(
inputPanel(
numericInput("n", "n", 10),
actionButton("update", "Update")
),
uiOutput("out")
)),
shinyServer(function(session, input, output) {
values <- reactiveValues()
# check if plot has been already rendered
check <- reactiveVal(FALSE)
values$data <- c()
observeEvent(input$update, {
# set check to TRUE
check(TRUE)
input$update
values$data <- c(values$data, runif(as.numeric(input$n), -10, 10))
dat <- values$data
output$plot <- renderPlot({
hist(dat)
})
})
# initial picture.
output$picture <- renderImage({
list(src = "temp.png")
}, deleteFile = FALSE)
output$out <- renderUI({
# in the beginning, check is FALSE and the picture is shown
if (!check()) {
imageOutput("picture")
} else {
# as soon as the button has been pressed the first time,
# the plot is shown
plotOutput("plot")
}
})
})
)
I know, that this has been solved a while, but I needed a solution, without uiOutput. Plus I find this much simpler.
library(shiny)
if (interactive()) {
shinyApp(
ui = fluidPage(
actionButton("btn", "Click me"),
br(),
plotOutput('some_plot', width = '100%')
),
server = function(input, output) {
output$some_plot <- renderPlot({
if (!input$btn) {
# default plot
plot(1, 1, col = 'red')
} else{
# updated plot
plot(1000, 1000, col = 'green')
}
})
}
)
}
I am working on an R-Shiny Application. I have used the following code(demo code) to interact with the plot.
ui <- shinyUI(fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
plotOutput("graph", width = "100%", click = "plot_click"),
verbatimTextOutput("click_info")
)
)
)
)
server <- shinyServer(function(input, output, session) {
observe({
output$graph <- renderPlot({
plot(1, 1)
})
})
# interaction click in graph
observe({
if(is.null(input$plot_click$x)) return(NULL)
x <- sample(20:30,1,F)
isolate({
output$graph <- renderPlot({
draw.single.venn(x)
})
})
})
})
shinyApp(ui=ui,server=server)
It can change the plot on a mouse click. I want to get back to the very first plot using a reset button. Kindly help.
I added a reset button to your sidebar. Hope that's helpful. This link provides more info on how to do this type of functionality.
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
actionButton("Reset", label="Reset Graph")
),
mainPanel(
plotOutput("graph", width = "100%", click = "plot_click"),
verbatimTextOutput("click_info")
)
)
)
)
server <- shinyServer(function(input, output, session) {
observeEvent(input$Reset,{ output$graph <- renderPlot({ plot(1, 1) }) }, ignoreNULL = F)
# interaction click in graph
observe({
if(is.null(input$plot_click$x)) return(NULL)
x <- sample(20:30,1,F)
isolate({
output$graph <- renderPlot({
draw.single.venn(x)
})
})
})
})
shinyApp(ui=ui,server=server)
I've been working with this post as a starting point.
Update handsontable by editing table and/or eventReactive
Very helpful, but I'm trying to extend it to specify the number of values in the table, then update a plot based on the table values after editing.
Here's what I have so far.
library(shiny)
library(rhandsontable)
library(colorSpec)
ui <- fluidPage(
numericInput("x", "number of values", 2),
rHandsontableOutput('table'),
textOutput('result'),
plotOutput('plot'),
actionButton("recalc", "generate new random vals and calculate")
)
server <- function(input,output,session)({
values <- reactiveValues(data=as.data.frame(runif(input$x)))
observe({
input$recalc
values$data <- as.data.frame(runif(input$x))
})
observe({
if(!is.null(input$table))
values$data <- hot_to_r(input$table)
})
output$table <- renderRHandsontable({
rhandsontable(values$data)
})
output$result <- renderText({
sum(values$data)
})
output$plot <- reactivePlot({
barplot(values$data)
})
})
shinyApp(ui = ui, server = server)
I get an error on the reactiveValues line because I'm trying to use input$x. The previous post had a hard coded value of 2.
I think you were almost there. You can, however, not use an input for creating a reactive value. But this is anyways not eneded and you can initiate it with a NULL.
library(shiny)
library(rhandsontable)
ui <- fluidPage(
numericInput("x", "number of values", 2),
rHandsontableOutput('table'),
textOutput('result'),
plotOutput('plot'),
actionButton("recalc", "generate new random vals and calculate")
)
server <- function(input,output,session)({
values <- reactiveValues(data = NULL) ## assign it with NULL
## button press resets now the data frame
observeEvent(input$recalc, {
values$data$x <- 0
})
## changes in numericInput sets all (!) new values
observe({
req(input$x)
values$data <- data.frame(x = runif(input$x))
})
observe({
if(!is.null(input$table))
values$data <- hot_to_r(input$table)
})
output$table <- renderRHandsontable({
req(values$data)
rhandsontable(values$data)
})
output$result <- renderText({
req(values$data)
sum(values$data)
})
output$plot <- renderPlot({
req(values$data)
barplot(values$data$x)
})
})
shinyApp(ui = ui, server = server)
You can use reactive() instead of reactiveValues to do this:
library(shiny)
library(rhandsontable)
library(colorSpec)
ui <- fluidPage(
numericInput("x", "number of values", 2),
rHandsontableOutput('table'),
textOutput('result')
)
server <- function(input,output,session)({
values <- reactive({
foo <- as.data.frame(runif(input$x))
colnames(foo) <- c("Col1")
return(foo)
})
output$table <- renderRHandsontable({
rhandsontable(values())
})
output$result <- renderText({
sum(values())
})
})
shinyApp(ui = ui, server = server)
I hope you can help me again as I stumbled over another problem in Shiny:
I would like a graphic to change in the moment it is clicked on. Here's a minimal example:
ui.R (shows a clickable graphic and a text frame)
shinyUI(fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
plotOutput("graph", width = "100%", click = "plot_click"),
verbatimTextOutput("click_info")
)
)
)
)
server.R (graphic just contains "A","B","C","D", on click I get the nearest letter in the text frame)
shinyServer(function(input, output, session) {
# Visualization output:
observe({
output$graph <- renderPlot({
data <- data.frame(x=c(1,2,1,2), y=c(1,1,2,2),
values=c("A","B","C","D"), stringsAsFactors=FALSE)
plot(data$x, data$y, pch=data$values)
})
})
# interaction click in graph
observe({
click <- c(input$plot_click$x, input$plot_click$y)
data <- data.frame(x=c(1,2,1,2), y=c(1,1,2,2),
values=c("A","B","C","D"), stringsAsFactors=FALSE)
nearest_point <- which.min(apply(data[,1:2], 1, function(a) sum(((click-a)^2))))
id <- data$values[nearest_point]
output$click_info <- renderPrint({
id
})
})
})
Now what I want is to mark the letter I clicked on in the graph, for example by another color. But all my tries failed so far.
Try this:
ui <- shinyUI(fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
plotOutput("graph", width = "100%", click = "plot_click"),
verbatimTextOutput("click_info")
)
)
)
)
server <- shinyServer(function(input, output, session) {
data <- data.frame(x=c(1,2,1,2), y=c(1,1,2,2),
values=c("A","B","C","D"), stringsAsFactors=FALSE)
# Visualization output:
observe({
output$graph <- renderPlot({
plot(data$x, data$y, pch=data$values)
})
})
# interaction click in graph
observe({
if(is.null(input$plot_click$x)) return(NULL)
click <- c(input$plot_click$x, input$plot_click$y)
print(click)
nearest_point <- which.min(apply(data[,1:2], 1, function(a) sum(((click-a)^2))))
id <- data$values[nearest_point]
output$click_info <- renderPrint({
id
})
color <- rep("black",length(data$x))
color[data$values==id] <- "red"
isolate({
output$graph <- renderPlot({
plot(data$x, data$y, pch=data$values, col=color)
})
})
})
})
shinyApp(ui=ui,server=server)
With ggplot2
Edited as per #bunks suggestions:
library(ggplot2)
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
plotOutput("graph", width = "100%", click = "plot_click"),
verbatimTextOutput("click_info")
)
)
))
server <- shinyServer(function(input, output, session) {
data <- data.frame(x=c(1,2,1,2),
y=c(1,1,2,2),
values=c("A","B","C","D"),
stringsAsFactors=FALSE,
color=rep("1",4))
makeReactiveBinding('data')
output$graph <- renderPlot({
ggplot(data=data,aes(x=x,y=y,label=values,color=color))+geom_text()+theme_classic()+guides(colour=FALSE)
})
observeEvent(input$plot_click, {
# Get 1 datapoint within 15 pixels of click, see ?nearPoints
np <- nearPoints(data, input$plot_click, maxpoints=1 , threshold = 15)
output$click_info <- renderPrint({np$values})
data$color <<- rep("1",length(data$x))
data$color[data$values==np$values] <<- "2"
})
})
shinyApp(ui=ui,server=server)