只是想知道是否有技巧/方法可以缓存通过我们闪亮的应用程序生成的图。
背景:
我们正在做一些计算密集型计算,最终导致绘图。我已经缓存(使用memoise)完成的计算,全局闪亮,但渲染绘图仍需要大约0.75秒。我只是想知道我们是否可以通过删除渲染图像所需的时间以及是否有光滑的方法来减少时间。
更多详情:
我正在使用网格来创建绘图(在这种情况下是热图。理想情况下,希望缓存是基于磁盘的,因为在内存中存储绘图不会扩展。
谢谢! -Abhi
答案 0 :(得分:6)
假设您正在使用ggplot
(使用Shiny,我敢打赌这是一个公平的假设)。
Plist
。 hash %in% names(Plist)
Plist[hash] <- new_graph
答案 1 :(得分:3)
Ricardo Saporta的答案非常好,我曾经解决过类似的问题,但我也想添加一个代码解决方案。
对于缓存,我使用了digest::digest()
,我只是将该特定图的参数列表提供给该函数以创建哈希字符串。我最初认为我必须从observe()
中提取哈希字符串然后使用if / else语句来确定是否应该根据图像是否将其发送到renderImage()
或renderPlot()
以前是创建过的。我fla fla这一段时间,然后偶然发现只是使用renderImage()
。它不是一个完美的图像替换,但足够接近本演示的目的。
ui.R
library(shiny)
fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 25),
selectInput("plot_color", "Barplot color",
c("green"="green",
"blue"="blue"))
),
mainPanel(
plotOutput("distPlot", width='100%', height='480px')
)
)
)
和server.R
library(shiny)
function(input, output) {
base <- reactive({
fn <- digest::digest(c(input$bins, input$plot_color))
fn})
output$distPlot <- renderImage({
filename <- paste0(base(), ".png")
if(filename %in% list.files()){
list(src=filename)
} else {
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
png(filename)
hist(x, breaks = bins, col = input$plot_color, border = 'white')
dev.off()
list(src=filename)
}
}, deleteFile = FALSE)
}
答案 2 :(得分:3)
虽然这个问题的答案都非常好,但我希望使用shiny modules添加另一个。以下模块将绘图函数和它的参数的反应版本作为输入。最后do.call(plotfun, args())
用于创建情节。
library(shiny)
cachePlot <- function(input, output, session, plotfun, args, width = 480, height = 480,
dir = tempdir(), prefix = "cachedplot", deleteonexit = TRUE){
hash <- function(args) digest::digest(args)
output$plot <- renderImage({
args <- args()
if (!is.list(args)) args <- list(args)
imgpath <- file.path(dir, paste0(prefix, "-", hash(args), ".png"))
if(!file.exists(imgpath)){
png(imgpath, width = width, height = height)
do.call(plotfun, args)
dev.off()
}
list(src = imgpath)
}, deleteFile = FALSE)
if (deleteonexit) session$onSessionEnded(function(){
imgfiles <- list.files(tempdir(), pattern = prefix, full.names = TRUE)
file.remove(imgfiles)
})
}
cachePlotUI <- function(id){
ns <- NS(id)
imageOutput(ns("plot"))
}
正如我们所看到的,模块删除了所需的图像文件,并提供了使用自定义缓存目录的选项,以防需要持久缓存(就像在我的实际用例中一样)。
对于一个用法示例,我将像Stedy一样使用hist(faithful[, 2])
示例。
histfaithful <- function(bins, col){
message("calling histfaithful with args ", bins, " and ", col)
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = bins + 1)
hist(x, breaks = bins, col = col, border = 'white')
}
shinyApp(
ui = fluidPage(
inputPanel(
sliderInput("bins", "bins", 5, 30, 10, 1),
selectInput("col", "color", c("blue", "red"))
),
cachePlotUI("cachedPlot")
),
server = function(input, output, session){
callModule(
cachePlot, "cachedPlot", histfaithful,
args = reactive(list(bins = input$bins, col = input$col))
)
}
)