I have a shiny
app and I want a ggplot
with a brush
at the start, so the user does not need to select certain area of interest every time the app starts. Later of course user can select different area. Here is an example to start with:
library(shiny)
library(ggplot2)
runApp(shinyApp(
ui = fluidPage(plotOutput('plotA', brush = brushOpts(id = 'plotA_brush')),
plotOutput('plotZ')),
server = function(input, output, session) {
pollData <- reactivePoll(60 * 1000, session,
checkFunc = function(){ Sys.time() },
valueFunc = function(){ data.frame(x = 1:100, y = cumsum(rnorm(100)))})
output$plotA <- renderPlot({
dt <- pollData()
ggplot(dt, aes(x, y)) + geom_line()
})
ranges <- reactiveValues(x = NULL, y = NULL)
observe({
brush <- input$plotA_brush
if(!is.null(brush)) {
ranges$x <- c(brush$xmin, brush$xmax)
ranges$y <- c(brush$ymin, brush$ymax)
} else {
ranges$x <- NULL
ranges$y <- NULL
}
})
output$plotZ <- renderPlot({
dt <- pollData()
ggplot(dt, aes(x, y)) + geom_line() + coord_cartesian(xlim = ranges$x, ylim = ranges$y)
})
}
))
With the Learn ggplot2 Shiny app, users can make plots using ggplot2 without having to code each step, reducing typos and error messages and allowing users to become familiar with ggplot2 code.
Shiny modules have two big advantages. Firstly, namespacing makes it easier to understand how your app works because you can write, analyse, and test individual components in isolation. Secondly, because modules are functions they help you reuse code; anything you can do with a function, you can do with a module.
Yes, it is possible.
In the code below I've added just a few lines. First, I've added set.seed(42)
so that the graphics are reproducible. Second, there is a dput(brush)
that has been commented out. This was helpful for identifying the initial brush that I wanted to have. Lastly, The in the observe
environment controlling the ranges
I have added a if
else
set to use the default brush
is it is a NULL
value from the input$plotA_brush
object.
library(shiny)
library(ggplot2)
set.seed(42)
runApp(shinyApp(
ui = fluidPage(plotOutput('plotA', brush = brushOpts(id = 'plotA_brush')),
plotOutput('plotZ')),
server = function(input, output, session) {
pollData <- reactivePoll(60 * 1000, session,
checkFunc = function(){ Sys.time() },
valueFunc = function(){ data.frame(x = 1:100, y = cumsum(rnorm(100)))})
output$plotA <- renderPlot({
dt <- pollData()
ggplot(dt, aes(x, y)) + geom_line()
})
ranges <- reactiveValues(x = NULL, y = NULL)
observe({
if (is.null(input$plotA_brush)) {
brush <- structure(list(xmin = 14.313925002001, xmax = 39.942241912585, ymin = 1.1077251080591, ymax = 5.5028180250535, mapping = structure(list( x = "x", y = "y"), .Names = c("x", "y")), domain = structure(list( left = -3.95, right = 104.95, bottom = -4.07771077213569, top = 9.69030145758825), .Names = c("left", "right", "bottom", "top")), range = structure(list(left = 32.3904099935947, right = 674.020527857828, bottom = 368.859578048224, top = 5.47945189149413), .Names = c("left", "right", "bottom", "top")), log = structure(list(x = NULL, y = NULL), .Names = c("x", "y")), direction = "xy", brushId = "plotA_brush", outputId = "plotA"), .Names = c("xmin", "xmax", "ymin", "ymax", "mapping", "domain", "range", "log", "direction", "brushId", "outputId"))
} else {
brush <- input$plotA_brush
}
# dput(brush) # Useful for finding the initial brush
if(!is.null(brush)) {
ranges$x <- c(brush$xmin, brush$xmax)
ranges$y <- c(brush$ymin, brush$ymax)
} else {
ranges$x <- NULL
ranges$y <- NULL
}
})
output$plotZ <- renderPlot({
dt <- pollData()
ggplot(dt, aes(x, y)) + geom_line() + coord_cartesian(xlim = ranges$x, ylim = ranges$y)
})
}
))
The initial starting page looks like this:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With