想知道是否有技巧/方法可以緩存通過我們的閃亮應用生成的情節。在R/Shiny中緩存情節
背景:
我們正在做的有些計算密集型計算,其最終導致的情節。我已經緩存(使用memoise)完成的計算,全局閃亮,但它仍然需要大約0.75秒來渲染一個情節。我只是想知道我們是否可以通過消除渲染圖像所需的時間來減少這些時間,以及是否已經做到了這一點。
更多細節:
我使用網格建立在這種情況下,圖(熱圖理想的情況下想緩存將基於磁盤的存儲在內存中地塊不會擴大
感謝。 ! -Abhi
想知道是否有技巧/方法可以緩存通過我們的閃亮應用生成的情節。在R/Shiny中緩存情節
背景:
我們正在做的有些計算密集型計算,其最終導致的情節。我已經緩存(使用memoise)完成的計算,全局閃亮,但它仍然需要大約0.75秒來渲染一個情節。我只是想知道我們是否可以通過消除渲染圖像所需的時間來減少這些時間,以及是否已經做到了這一點。
更多細節:
我使用網格建立在這種情況下,圖(熱圖理想的情況下想緩存將基於磁盤的存儲在內存中地塊不會擴大
感謝。 ! -Abhi
假設你正在使用ggplot
(其具有光澤,我敢打賭是一個合理的假設)。
Plist
。hash %in% names(Plist)
Plist[hash] <- new_graph
裏卡多薩波塔答案是非常好,是我用來解決類似的問題,但我想添加一個代碼解決方案。
對於緩存我使用digest::digest()
其中我只是將該特定圖的參數列表添加到該函數以創建哈希字符串。我最初認爲我必須從observe()
中提取散列字符串,然後使用if/else語句來確定是否應該根據圖像是否曾經創建過,根據其是否發送到renderImage()
或renderPlot()
。我與這個混淆了一段時間,然後偶然發現只使用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)
}
雖然兩者這個問題的答案都非常好,我想也添加使用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))
)
}
)
查看'?renderImage'上的例子,它可能會給你一些想法。基本上你想要一個記憶劇情功能,返回一個PNG文件,我想;並使用renderImage來調用該memoized函數。 –
謝謝喬。關於我們如何能夠自動縮放通過renderImage渲染的靜態圖像的任何想法。 – Abhi