mirror of
https://github.com/rstudio/shiny.git
synced 2026-02-08 05:35:07 -05:00
317 lines
12 KiB
R
317 lines
12 KiB
R
% Generated by roxygen2: do not edit by hand
|
|
% Please edit documentation in R/render-cached-plot.R
|
|
\name{renderCachedPlot}
|
|
\alias{renderCachedPlot}
|
|
\title{Plot output with cached images}
|
|
\usage{
|
|
renderCachedPlot(expr, cacheKeyExpr, sizePolicy = sizeGrowthRatio(width =
|
|
400, height = 400, growthRate = 1.2), res = 72, cache = "app", ...,
|
|
outputArgs = list())
|
|
}
|
|
\arguments{
|
|
\item{expr}{An expression that generates a plot.}
|
|
|
|
\item{cacheKeyExpr}{An expression that returns a cache key. This key should
|
|
be a unique identifier for a plot: the assumption is that if the cache key
|
|
is the same, then the plot will be the same.}
|
|
|
|
\item{sizePolicy}{A function that takes two arguments, \code{width} and
|
|
\code{height}, and returns a list with \code{width} and \code{height}. The
|
|
purpose is to round the actual pixel dimensions from the browser to some
|
|
other dimensions, so that this will not generate and cache images of every
|
|
possible pixel dimension. See \code{\link{sizeGrowthRatio}} for more
|
|
information on the default sizing policy.}
|
|
|
|
\item{res}{The resolution of the PNG, in pixels per inch.}
|
|
|
|
\item{cache}{The scope of the cache, or a cache object. This can be
|
|
\code{"app"} (the default), \code{"session"}, or a cache object like
|
|
a \code{\link{diskCache}}. See the Cache Scoping section for more
|
|
information.}
|
|
|
|
\item{...}{Arguments to be passed through to \code{\link[grDevices]{png}}.
|
|
These can be used to set the width, height, background color, etc.}
|
|
|
|
\item{outputArgs}{A list of arguments to be passed through to the implicit
|
|
call to \code{\link{plotOutput}} when \code{renderPlot} is used in an
|
|
interactive R Markdown document.}
|
|
}
|
|
\description{
|
|
Renders a reactive plot, with plot images cached to disk.
|
|
}
|
|
\details{
|
|
\code{expr} is an expression that generates a plot, similar to that in
|
|
\code{renderPlot}. Unlike with \code{renderPlot}, this expression does not
|
|
take reactive dependencies. It is re-executed only when the cache key
|
|
changes.
|
|
|
|
\code{cacheKeyExpr} is an expression which, when evaluated, returns an object
|
|
which will be serialized and hashed using the \code{\link[digest]{digest}}
|
|
function to generate a string that will be used as a cache key. This key is
|
|
used to identify the contents of the plot: if the cache key is the same as a
|
|
previous time, it assumes that the plot is the same and can be retrieved from
|
|
the cache.
|
|
|
|
This \code{cacheKeyExpr} is reactive, and so it will be re-evaluated when any
|
|
upstream reactives are invalidated. This will also trigger re-execution of
|
|
the plotting expression, \code{expr}.
|
|
|
|
The key should consist of "normal" R objects, like vectors and lists. Lists
|
|
should in turn contain other normal R objects. If the key contains
|
|
environments, external pointers, or reference objects -- or even if it has
|
|
such objects attached as attributes -- then it is possible that it will
|
|
change unpredictably even when you do not expect it to. Additionally, because
|
|
the entire key is serialized and hashed, if it contains a very large object
|
|
-- a large data set, for example -- there may be a noticeable performance
|
|
penalty.
|
|
|
|
If you face these issues with the cache key, you can work around them by
|
|
extracting out the important parts of the objects, and/or by converting them
|
|
to normal R objects before returning them. Your expression could even
|
|
serialize and hash that information in an efficient way and return a string,
|
|
which will in turn be hashed (very quickly) by the
|
|
\code{\link[digest]{digest}} function.
|
|
|
|
Internally, the result from \code{cacheKeyExpr} is combined with the name of
|
|
the output (if you assign it to \code{output$plot1}, it will be combined
|
|
with \code{"plot1"}) to form the actual key that is used. As a result, even
|
|
if there are multiple plots that have the same \code{cacheKeyExpr}, they
|
|
will not have cache key collisions.
|
|
}
|
|
\section{Cache scoping}{
|
|
|
|
|
|
There are a number of different ways you may want to scope the cache. For
|
|
example, you may want each user session to have their own plot cache, or
|
|
you may want each run of the application to have a cache (shared among
|
|
possibly multiple simultaneous user sessions), or you may want to have a
|
|
cache that persists even after the application is shut down and started
|
|
again.
|
|
|
|
To control the scope of the cache, use the \code{cache} parameter. There
|
|
are two ways of having Shiny automatically create and clean up the disk
|
|
cache.
|
|
|
|
\describe{
|
|
\item{1}{To scope the cache to one run of a Shiny application (shared
|
|
among possibly multiple user sessions), use \code{cache="app"}. This
|
|
is the default. The cache will be shared across multiple sessions, so
|
|
there is potentially a large performance benefit if there are many users
|
|
of the application. When the application stops running, the cache will
|
|
be deleted. If plots cannot be safely shared across users, this should
|
|
not be used.}
|
|
\item{2}{To scope the cache to one session, use \code{cache="session"}.
|
|
When a new user session starts -- in other words, when a web browser
|
|
visits the Shiny application -- a new cache will be created on disk
|
|
for that session. When the session ends, the cache will be deleted.
|
|
The cache will not be shared across multiple sessions.}
|
|
}
|
|
|
|
If either \code{"app"} or \code{"session"} is used, the cache will be 10 MB
|
|
in size, and will be stored stored in memory, using a
|
|
\code{\link{memoryCache}} object. Note that the cache space will be shared
|
|
among all cached plots within a single application or session.
|
|
|
|
In some cases, you may want more control over the caching behavior. For
|
|
example, you may want to use a larger or smaller cache, share a cache
|
|
among multiple R processes, or you may want the cache to persist across
|
|
multiple runs of an application, or even across multiple R processes.
|
|
|
|
To use different settings for an application-scoped cache, you can call
|
|
\code{\link{shinyOptions}()} at the top of your app.R, server.R, or
|
|
global.R. For example, this will create a cache with 20 MB of space
|
|
instead of the default 10 MB:
|
|
\preformatted{
|
|
shinyOptions(cache = memoryCache(size = 20e6))
|
|
}
|
|
|
|
To use different settings for a session-scoped cache, you can call
|
|
\code{\link{shinyOptions}()} at the top of your server function. To use
|
|
the session-scoped cache, you must also call \code{renderCachedPlot} with
|
|
\code{cache="session"}. This will create a 20 MB cache for the session:
|
|
\preformatted{
|
|
function(input, output, session) {
|
|
shinyOptions(cache = memoryCache(size = 20e6))
|
|
|
|
output$plot <- renderCachedPlot(
|
|
...,
|
|
cache = "session"
|
|
)
|
|
}
|
|
}
|
|
|
|
If you want to create a cache that is shared across multiple concurrent
|
|
R processes, you can use a \code{\link{diskCache}}. You can create an
|
|
application-level shared cache by putting this at the top of your app.R,
|
|
server.R, or global.R:
|
|
\preformatted{
|
|
shinyOptions(cache = diskCache(file.path(dirname(tempdir()), "myapp-cache"))
|
|
}
|
|
|
|
This will create a subdirectory in your system temp directory named
|
|
\code{myapp-cache} (replace \code{myapp-cache} with a unique name of
|
|
your choosing). On most platforms, this directory will be removed when
|
|
your system reboots. This cache will persist across multiple starts and
|
|
stops of the R process, as long as you do not reboot.
|
|
|
|
To have the cache persist even across multiple reboots, you can create the
|
|
cache in a location outside of the temp directory. For example, it could
|
|
be a subdirectory of the application:
|
|
\preformatted{
|
|
shinyOptions(cache = diskCache("./myapp-cache"))
|
|
}
|
|
|
|
In this case, resetting the cache will have to be done manually, by deleting
|
|
the directory.
|
|
|
|
You can also scope a cache to just one plot, or selected plots. To do that,
|
|
create a \code{\link{memoryCache}} or \code{\link{diskCache}}, and pass it
|
|
as the \code{cache} argument of \code{renderCachedPlot}.
|
|
}
|
|
|
|
\section{Interactive plots}{
|
|
|
|
|
|
\code{renderCachedPlot} can be used to create interactive plots. See
|
|
\code{\link{plotOutput}} for more information and examples.
|
|
}
|
|
|
|
\examples{
|
|
## Only run examples in interactive R sessions
|
|
if (interactive()) {
|
|
|
|
# A basic example that uses the default app-scoped memory cache.
|
|
# The cache will be shared among all simultaneous users of the application.
|
|
shinyApp(
|
|
fluidPage(
|
|
sidebarLayout(
|
|
sidebarPanel(
|
|
sliderInput("n", "Number of points", 4, 32, value = 8, step = 4)
|
|
),
|
|
mainPanel(plotOutput("plot"))
|
|
)
|
|
),
|
|
function(input, output, session) {
|
|
output$plot <- renderCachedPlot({
|
|
Sys.sleep(2) # Add an artificial delay
|
|
seqn <- seq_len(input$n)
|
|
plot(mtcars$wt[seqn], mtcars$mpg[seqn],
|
|
xlim = range(mtcars$wt), ylim = range(mtcars$mpg))
|
|
},
|
|
cacheKeyExpr = { list(input$n) }
|
|
)
|
|
}
|
|
)
|
|
|
|
|
|
|
|
# An example uses a data object shared across sessions. mydata() is part of
|
|
# the cache key, so when its value changes, plots that were previously
|
|
# stored in the cache will no longer be used (unless mydata() changes back
|
|
# to its previous value).
|
|
mydata <- reactiveVal(data.frame(x = rnorm(400), y = rnorm(400)))
|
|
|
|
ui <- fluidPage(
|
|
sidebarLayout(
|
|
sidebarPanel(
|
|
sliderInput("n", "Number of points", 50, 400, 100, step = 50),
|
|
actionButton("newdata", "New data")
|
|
),
|
|
mainPanel(
|
|
plotOutput("plot")
|
|
)
|
|
)
|
|
)
|
|
|
|
server <- function(input, output, session) {
|
|
observeEvent(input$newdata, {
|
|
mydata(data.frame(x = rnorm(400), y = rnorm(400)))
|
|
})
|
|
|
|
output$plot <- renderCachedPlot(
|
|
{
|
|
Sys.sleep(2)
|
|
d <- mydata()
|
|
seqn <- seq_len(input$n)
|
|
plot(d$x[seqn], d$y[seqn], xlim = range(d$x), ylim = range(d$y))
|
|
},
|
|
cacheKeyExpr = { list(input$n, mydata()) },
|
|
)
|
|
}
|
|
|
|
shinyApp(ui, server)
|
|
|
|
|
|
# A basic application with two plots, where each plot in each session has
|
|
# a separate cache.
|
|
shinyApp(
|
|
fluidPage(
|
|
sidebarLayout(
|
|
sidebarPanel(
|
|
sliderInput("n", "Number of points", 4, 32, value = 8, step = 4)
|
|
),
|
|
mainPanel(
|
|
plotOutput("plot1"),
|
|
plotOutput("plot2")
|
|
)
|
|
)
|
|
),
|
|
function(input, output, session) {
|
|
output$plot1 <- renderCachedPlot({
|
|
Sys.sleep(2) # Add an artificial delay
|
|
seqn <- seq_len(input$n)
|
|
plot(mtcars$wt[seqn], mtcars$mpg[seqn],
|
|
xlim = range(mtcars$wt), ylim = range(mtcars$mpg))
|
|
},
|
|
cacheKeyExpr = { list(input$n) },
|
|
cache = memoryCache()
|
|
)
|
|
output$plot2 <- renderCachedPlot({
|
|
Sys.sleep(2) # Add an artificial delay
|
|
seqn <- seq_len(input$n)
|
|
plot(mtcars$wt[seqn], mtcars$mpg[seqn],
|
|
xlim = range(mtcars$wt), ylim = range(mtcars$mpg))
|
|
},
|
|
cacheKeyExpr = { list(input$n) },
|
|
cache = memoryCache()
|
|
)
|
|
}
|
|
)
|
|
|
|
}
|
|
|
|
\dontrun{
|
|
# At the top of app.R, this set the application-scoped cache to be a memory
|
|
# cache that is 20 MB in size, and where cached objects expire after one
|
|
# hour.
|
|
shinyOptions(cache = memoryCache(max_size = 20e6, max_age = 3600))
|
|
|
|
# At the top of app.R, this set the application-scoped cache to be a disk
|
|
# cache that can be shared among multiple concurrent R processes, and is
|
|
# deleted when the system reboots.
|
|
shinyOptions(cache = diskCache(file.path(dirname(tempdir()), "myapp-cache"))
|
|
|
|
# At the top of app.R, this set the application-scoped cache to be a disk
|
|
# cache that can be shared among multiple concurrent R processes, and
|
|
# persists on disk across reboots.
|
|
shinyOptions(cache = diskCache("./myapp-cache"))
|
|
|
|
# At the top of the server function, this set the session-scoped cache to be
|
|
# a memory cache that is 5 MB in size.
|
|
server <- function(input, output, session) {
|
|
shinyOptions(cache = memoryCache(max_size = 5e6))
|
|
|
|
output$plot <- renderCachedPlot(
|
|
...,
|
|
cache = "session"
|
|
)
|
|
}
|
|
|
|
}
|
|
}
|
|
\seealso{
|
|
See \code{\link{renderPlot}} for the regular, non-cached version of
|
|
this function. For more about configuring caches, see
|
|
\code{\link{memoryCache}} and \code{\link{diskCache}}.
|
|
}
|