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.
Related
I know renderPlot produces plot that can be shown on Shiny plotOutput function. I also know autoinvalidate() helps to calculate data reactively.
I am displaying a radar chart (in fact can be any chart) using the below codes:
output$plot2 <- renderPlot({
autoInvalidate()
p2<<-ggradar(mtcars_radar[i,])
})
What I dont know is how to change the value of i from 1 to 300 during every event of autoinvalidate().
Or is there anyway I can change the row of data in plot so that the plot is dynamically animating every sec with a new row of data.
Can anyone help me plz?
The full code is here:
library(shiny)
library(ggplot2)
mtcars %>%
rownames_to_column( var = "group" ) %>%
mutate_at(vars(-group),funs(rescale)) %>%
tail(4) %>% select(1:10) -> mtcars_radar
ui <- fluidPage(
sidebarPanel(
actionButton("button", "Go!")
),
# Show the plot
mainPanel(
plotOutput("plot2")
)
)
server <- function(input, output) {
library(ggplot2)
library(ggradar)
suppressPackageStartupMessages(library(dplyr))
library(scales)
autoInvalidate <- reactiveTimer(2000)
plot2 <- NULL
output$plot2 <- renderPlot({
ggradar(mtcars_radar[1,])
})
observeEvent(input$button,{
output$plot2 <- renderPlot({
autoInvalidate()
p2<<-ggradar(mtcars_radar[i,])
p2
})
})
}
# Run the application
shinyApp(ui = ui, server = server)
Any help please?
This is where you need a reactive value that stores the row index and changes every second. I do not have the library ggradar, so I will just print out the current row index value instead. I also used invalidateLater instead of reactiveTimer as suggested by Shiny documentation.
library(shiny)
ui <- fluidPage(
verbatimTextOutput("debug")
)
server <- function(input, output) {
row_idx_max <- 15
row_idx <- reactiveVal(0)
observe({
isolate(row_idx(row_idx() + 1))
cur_row_idx <- isolate(row_idx())
if (cur_row_idx < row_idx_max) {
invalidateLater(1000)
}
})
output$debug <- renderPrint({
row_idx()
})
}
shinyApp(ui, server)
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)
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)`
I'd like to create data once and reuse it in multiple plots. The example below creates the data in each plot, but how can I create it once (x) and have each plot use x?
ui <- shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
numericInput(inputId = "mean", label = "Mean", value = 50)
),
mainPanel(
column(6,plotOutput(outputId = "hist1")
),
column(6,plotOutput(outputId = "hist2")
)
)
)
)
)
server <- function(input,output){
# I'd like to create the data just once here, and then reuse it in each plot
# x <- rnorm(100,input$mean,5)
output$hist1 <- renderPlot({
hist(rnorm(100,input$mean,5))
#hist(x)
})
output$hist2 <- renderPlot({
hist(rnorm(100,input$mean,5))
#hist(x)
})
}
runApp(list(ui = ui, server = server))
You can wrap your rnorm in a reactive expression to create a reactive conductor. Then, use the conductor in your endpoints (output$). See http://shiny.rstudio.com/articles/reactivity-overview.html.
server <- function(input,output){
# I'd like to create the data just once here, and then reuse it in each plot
x <- reactive(rnorm(100, input$mean, 5))
output$hist1 <- renderPlot({
hist(x())
})
output$hist2 <- renderPlot({
hist(x())
})
}
Wrapping the server codes with observe would do the job.
server <- function(input,output){
# I'd like to create the data just once here, and then reuse it in each plot
observe({
data <- rnorm(100,input$mean,5)
output$hist1 <- renderPlot({
hist(data)
#hist(rnorm(100,x,5))
})
output$hist2 <- renderPlot({
hist(data)
#hist(rnorm(100,x,5))
})
})
}
I'm exploring the possibilities with interactive ggplot2 in shiny. Inspired by this I created a shiny app that exclude points from a dataset and plots the data where the excluded points are of a different color.
app.R
library(shiny)
library(ggplot2)
server<-function(input, output) {
data <- reactive({
set.seed(10)
df=data.frame(x=rnorm(100),y=rnorm(100))
df
})
vals<-reactiveValues(keeprows=rep(TRUE, 100))
output$plot1 <- renderPlot({
df=data()
keep=df[vals$keeprows, ,drop=FALSE]
exclude=df[!vals$keeprows, ,drop=FALSE]
plot=ggplot(data=keep,aes(x,y))+geom_point()+theme_bw()+
geom_point(data=exclude,fill=NA,col="black",alpha=0.75,shape=21)
plot
})
observeEvent(input$plot1_click,{
df=data()
res <- nearPoints(df, input$plot1_click, allRows = TRUE,threshold=5)
vals$keeprows <- xor(vals$keeprows, res$selected_)
})
}
ui <- fluidPage(
titlePanel("Reactive test"),
mainPanel(
plotOutput("plot1",click="plot1_click")
)
)
shinyApp(ui = ui, server = server)
This works perfectly, but now I want to be able to define vals with:
vals<-reactiveValues(keeprows=rep(TRUE,nrow(CustomDataInput))
In the case of my example, I tried accessing number of rows from the data created in data():
vals<-reactiveValues(keeprows=rep(TRUE,nrow(data()))
This gives me an error because I tried to access a reactive variable in a non-reactive environment. Is there a way to access the data created in a reactive function to define reactiveValues?
Thank you for your time!
The error pretty much addresses the problem. The correct way to do this is as follows.
library(shiny)
library(ggplot2)
server<-function(input, output) {
vals <- reactiveValues()
data <- reactive({
set.seed(10)
df=data.frame(x=rnorm(100),y=rnorm(100))
vals$keeprows = rep(TRUE,nrow(df))
df
})
#vals<-reactiveValues(keeprows=rep(TRUE,100))
output$plot1 <- renderPlot({
df=data()
keep=df[vals$keeprows, ,drop=FALSE]
exclude=df[!vals$keeprows, ,drop=FALSE]
plot=ggplot(data=keep,aes(x,y))+geom_point()+theme_bw()+
geom_point(data=exclude,fill=NA,col="black",alpha=0.75,shape=21)
plot
})
observeEvent(input$plot1_click,{
df=data()
res <- nearPoints(df, input$plot1_click, allRows = TRUE,threshold=5)
vals$keeprows <- xor(vals$keeprows, res$selected_)
})
}
ui <- fluidPage(
titlePanel("Reactive test"),
mainPanel(
plotOutput("plot1",click="plot1_click")
)
)
shinyApp(ui = ui, server = server)
Declare the vals variable before hand and use that in reactive() function to send variables to vals as shown above. You should be fine.