Can't clear the plot in my R shiny app - r

I teach basic statistics at a local university and am trying to build an app where students can explore the relationship between scatterplots and the Pearson correlation coefficient. I can generate a blank plot and users can click inside the plot to generate points. As points are added a correlation coefficient is displayed. I can clear the map using a reset button; however, i cannot reset the previous points.
I tried assigning the list storing the points to NULL, but for the life I have no clue how to do it.
Any suggestion on clearing the graph so users can start over with a new scatterplot would be greatly appreciated.
A link to a 'working' app: https://uky994.shinyapps.io/ggplotcoords/
My code:
`ui <- shinyUI(fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(
actionButton("reset", "Reset!")
),
mainPanel(
plotOutput("graph", width = "100%", click = "plot_click"),
verbatimTextOutput("click_info")
)
)
)
)
server <- shinyServer(function(input, output, session) {
observeEvent(input$reset, {
output$graph <- renderPlot({
plot(data$x, data$y, pch=data$values,col="white",xlim=c(0,100),
ylim=c(0,100),xlab="X",ylab="Y")
})
points$x<-NULL
points$y<-NULL
})
points <- list(x=vector("numeric", 0), y=vector("numeric", 0))
data <- data.frame(x=c(0,100,0,100), y=c(0,0,100,100),
values=c("A","B","C","D"), stringsAsFactors=FALSE)
# Visualization output:
observe({
output$graph <- renderPlot({
plot(data$x, data$y,
pch=data$values,col="white",xlim=c(0,100),
ylim=c(0,100),xlab="X",ylab="Y")
})
})
#v=input$plot_click$x
# interaction click in graph
observe({
if(is.null(input$plot_click$x)) return(NULL)
print(points)
points$x <<- c(points$x, isolate(input$plot_click$x))
points$y <<- c(points$y, isolate(input$plot_click$y))
output$graph <- renderPlot({
plot(points$x, points$y,pch=20,col="#7fcdbb",xlim=c(0,100),
ylim=c(0,100),xlab="X",ylab="Y")
})
output$click_info <- renderPrint({
cat("Correlation is:\n")
cor(points$x, points$y)
#length(points$x)
})
})
})
shinyApp(ui=ui,server=server)`

Related

attempt to apply non-function

I'm trying to build a simple application that draws a histogram of a selected variable based on a subset filtered by the other input. I get the error in the line hist(dataX()$datasetInput()) which should return dataX$mpg. How can I fix it?
Full code:
library(shiny)
u <- shinyUI(pageWithSidebar(
headerPanel("Staz w bezrobociu"),
sidebarPanel(
selectInput("variable", "Variable:",
list("Milles/gallon",
"Horse power")
),
textInput("nc","Number of cylinders",value = 6)
),
mainPanel(
plotOutput("Plot")
)
))
s <- shinyServer(function(input, output)
{
dataX <- reactive({mtcars[mtcars$cyl==input$nc,,drop = FALSE]})
datasetInput <- reactive({
switch(input$variable,
"Milles/gallon" = mpg,
"Horse power" = hp)
})
output$Plot <- renderPlot({
hist(dataX()$datasetInput())
})
})
shinyApp(u,s)
You complicated the simple app.
You do not need to list all the columns in selectInput. You can just render it from the server side.
Same applies to the cylinders
Shortcuts like u and sare acceptable, but just stick to the naming conventions. It makes your life easy.
Below is a complete working app
library(shiny)
ui <- shinyUI(pageWithSidebar(
headerPanel("Staz w bezrobociu"),
sidebarPanel(uiOutput("SelectColname"),
uiOutput("Cylinders")),
mainPanel(plotOutput("Plot"))
))
server <- shinyServer(function(input, output){
# Create a reactive dataset
dataX <- reactive({
mtcars
})
# Output number cylinders as select box
output$Cylinders <- renderUI({
selectInput("cylinders", "cylinders:", unique(dataX()$cyl))
})
# Output column names as selectbox
output$SelectColname <- renderUI({
selectInput("variable", "Variable:", colnames(dataX()[,c(1,4)]))
})
# Based on the selection by user, create an eventreactive plotdata object
plotdata <- eventReactive(input$cylinders, {
plotdata = dataX()[dataX()$cyl == input$cylinders, , drop = FALSE]
})
# Render the plot, the plot changes when new cylinder is selected
output$Plot <- renderPlot({
if (is.null(plotdata()))
return(NULL)
hist(
plotdata()[, input$variable],
xlab = input$variable,
main = paste(
"Histogram of" ,
input$variable
)
)
})
})
shinyApp(ui, server)

Treating plotOutput("plot_click") for each subplot separately

I have been playing around with plotOutput("plot_click") in Shiny. It seems pretty straightforward in most plots. Rather than returning the pixel x and pixel y value for a mouse click, it returns the x and y value scaled to the plot of interest for a mouse click. A app.R example is below -
library(shiny)
ui <- basicPage(
plotOutput("plot1", click = "plot_click"),
verbatimTextOutput("info")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
qplot(mtcars$wt, mtcars$mpg)
})
output$info <- renderText({
paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y)
})
}
shinyApp(ui, server)
I would like to extend upon this functionality so that I can obtain the x and y value scaled to a subplot of interest for a mouse click. I am interested in this when working with plot matrices. An app.R example is below -
library(shiny)
ui <- basicPage(
plotOutput("plot1", click = "plot_click"),
verbatimTextOutput("info")
)
server <- function(input, output) {
data <- select(mtcars,wt,mpg,qsec)
output$plot1 <- renderPlot({
ggpairs(data)
})
output$info <- renderText({
paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y)
})
}
shinyApp(ui, server)
I am only interested in the bottom-left three subplots. When I mouse click at any area of these bottom-left three subplots, however, I get the x and y values scaled for the entire plot. Is it possible to change this so that I could get the values for the x and y values scaled for each subplot accurately? Note: I am not interested in any points outside of these three bottom left subplots, and would not care to loose their interactive functionality if needed. Please kindly share any ideas!

R shiny: How to create an output which serves as an input in shiny?

My task is to:
random two independent variables (A and B) from their normal distributions
display their histograms,
random 3rd variable (C) which distribution depends on the value B,
display the histogram of C.
I'd like all three histograms to be sensitive to changes in inputs.
The histograms of A and B are reactive.
What can I do with C? Any help would be appreciated.
Here is my try:
ui:
library(shiny)
fluidPage(
titlePanel("Random"),
sidebarLayout(
sidebarPanel(
sliderInput("obs",
"Number of observations:",
min = 1,
max = 100,
value = 50)
),
mainPanel(
tabsetPanel(type="tabs",
tabPanel("plot 1 and plot 2",plotOutput("plot1"), plotOutput("plot2")),
tabPanel("plot 3",plotOutput("plot3"))
))))
server:
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
{
values_B <-rnorm(input$obs, 25,6)
assign('B_values', round(values_B), envir=.GlobalEnv)
hist(B_values, main="Histogram of B values", xlab="values")}
})
output$plot2 <- renderPlot({
values_A<-rnorm(input$obs,20, 4.5)
assign('A_values', round(values_A), envir=.GlobalEnv)
hist(A_values, main="Histogram of A values", xlab="values")
})
output$plot3 <- renderPlot({
category <- function(x) if ( x <=10) round(rnorm(1,50,10)) else round(rnorm(1,10,2))
assign('C_values', as.numeric(lapply(B_values, category)))
hist(C)
})
})
The reason this isn't working is because you need to create a reactive variable with your B_values as you cannot define a reactive variable within the renderPlot function and use it again therefore your code won't work in plot 3 as you have the dependency on the variable in plot1. You must define this as a reactive value as shown and then call it in your renderPlot.
Note that when calling a reactive variable you must use brackets after the variable name.
I would recommend that you watch the shiny tutorial on the shiny website it is very helpful in understanding how reactivity works.
Here is the server side for your example such that it works.
shinyServer(function(input, output) {
reactiveB <- reactive({
rnorm(input$obs, 25,6)
})
output$plot1 <- renderPlot({
{
values_B <- reactiveB()
assign('B_values', round(values_B), envir=.GlobalEnv)
hist(B_values, main="Histogram of B values", xlab="values")}
})
output$plot2 <- renderPlot({
values_A<-rnorm(input$obs,20, 4.5)
assign('A_values', round(values_A), envir=.GlobalEnv)
hist(A_values, main="Histogram of A values", xlab="values")
})
output$plot3 <- renderPlot({
B_values <- reactiveB()
category <- function(x) if ( x <=10) round(rnorm(1,50,10)) else round(rnorm(1,10,2))
assign('C_values', as.numeric(lapply(B_values, category)))
hist(C_values)
})
})

Mouse click event in rshiny

I'm trying to use click events using the plot_click option in RShiny. What I want to do is:I want to select a particular bubble from the first chart and then the chart below should be populated only for the above selected car. How to do this? Here is my code :
ui <- basicPage(
plotOutput("plot1", click = "plot_click"),
plotOutput("plot2")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
plot(mt$wt, mt$mpg)
})
output$plot2 <- renderPlot({
test <- data.frame(nearPoints(mt, input$plot_click, xvar = "wt", yvar = "mpg"))
test2 <- filter(test,Car_name)
car <- test2[1,1]
mt2 <- filter(mt,Car_name == car)
plot(mt2$wt,mt2$mpg)
})
}
shinyApp(ui, server)
I rearranged your server-function a bit. I moved the selected points to a reactive Value, which can be used by print/plot outputs.
Furthermore, i am not exactly sure what you want to achievewith all that filtering. Maybe you could change your original question an make a reproducible example out of it with the mtcars-data, as it seems you are using that.
library(shiny)
ui <- basicPage(
plotOutput("plot1", click = "plot_click"),
verbatimTextOutput("info"),
plotOutput("plot2")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
plot(mtcars$wt, mtcars$mpg)
})
selected_points <- reactiveValues(pts = NULL)
observeEvent(input$plot_click, {
x <- nearPoints(mtcars, input$plot_click, xvar = "wt", yvar = "mpg")
selected_points$pts <- x
})
output$info <- renderPrint({
selected_points$pts
})
output$plot2 <- renderPlot({
req(input$plot_click)
test <- selected_points$pts
plot(test$wt,test$mpg)
})
}
shinyApp(ui, server)
The clicked points are stored in the selected_points reactive Value, which is assigned in the observeEvent function.
If you filter a lot in the plot2-function, you would have to use req() or validate(), as it may be possible that no value is left over and therefore nothing can be plotted.
I hope that helps.

Interactive plotting in shiny using mouse clicks

I am doing a project where I use the shiny server and connect R to mongodb to fetch results from database and display it dynamically.
However, I face the following problem in it. I initially get the results from db and make a plot. After this plot is done, I want the user to make make two mouse clicks on the plot based on which it should take the two values as xlim and plot a zoomed version of the previous plot. However, I am not able to do it successfully.
Here is the code that I have written.
ui.R
library(shiny)
shinyUI(fluidPage(
titlePanel("LOAD AND PERFORMANCE DASHBOARD"),
sidebarLayout(
sidebarPanel(
fluidRow(
selectInput("select", label = h3("Select type of testing"),
choices = list("Performance Testing"=1, "Capacity Testing"=2)),
radioButtons("radio", label = h3("Select parameter to plot"),
choices = list("Disk" = 1, "Flit" = 2,"CPU" = 3,"Egress" =4,
"Memory" = 5))
)),
mainPanel(
plotOutput("plot",clickId="plot_click"),
textOutput("text1"),
plotOutput("plot2")
)
)
))
server.R
library(shiny)
library(rmongodb)
cursor <- vector()
shinyServer(function(input, output) {
initialize <- reactive({
mongo = mongo.create(host = "localhost")
})
calculate <- reactive({
if(input$radio==1)
xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "disk")
else if(input$radio==2)
xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "flit")
else if(input$radio==3)
xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "cpu")
else if(input$radio==4)
xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "egress")
else if(input$radio==5)
xvalue <- mongo.distinct(mongo,ns = "mydb.vload", "memory")
})
output$plot <- renderPlot({
initialize()
value <- calculate()
plot(value,xlab="Time",ylab="% Consumed")
lines(value)
cursor <- value
})
output$text1 <- renderText({
paste("You have selected",input$plot_click$x)
})
output$plot2 <- renderPlot({
plot(cursor[cursor<input$plot_click$x && cursor>first_click ],xlab="Time",ylab="% Consumed") lines(cursor)
first_click <- input$plot_click$x
})
})
Thanks in advance for the help :)
Here's a simple example that demonstrates the behavior you want, just run this code (or save as a file and source it). This code uses the new observeEvent function that debuted in Shiny 0.11, which just hit CRAN over the weekend.
The basic idea is that we track two reactive values, click1 and range. click1 represents the first mouse click, if any exists; and range represents the x-values of both mouse clicks. Clicking on the plot simply manipulates these two reactive values, and the plotting operation reads them.
library(shiny)
ui <- fluidPage(
h1("Plot click demo"),
plotOutput("plot", clickId = "plot_click"),
actionButton("reset", "Reset zoom")
)
server <- function(input, output, session) {
v <- reactiveValues(
click1 = NULL, # Represents the first mouse click, if any
range = NULL # After two clicks, this stores the range of x
)
# Handle clicks on the plot
observeEvent(input$plot_click, {
if (is.null(v$click1)) {
# We don't have a first click, so this is the first click
v$click1 <- input$plot_click
} else {
# We already had a first click, so this is the second click.
# Make a range from the previous click and this one.
v$range <- range(v$click1$x, input$plot_click$x)
# And clear the first click so the next click starts a new
# range.
v$click1 <- NULL
}
})
observeEvent(input$reset, {
# Reset both the range and the first click, if any.
v$range <- NULL
v$click1 <- NULL
})
output$plot <- renderPlot({
plot(cars, xlim = v$range)
if (!is.null(v$click1$x))
abline(v = v$click1$x)
})
}
shinyApp(ui, server)

Resources