2014-06-12 5 views
7

반짝이는 앱을 통해 플롯을 생성 할 수있는 트릭/방법이 있는지 궁금합니다.R/Shiny의 캐싱 플롯

배경 :

우리는 마침내 음모가 발생할 집중적 인 계산을 계산 다소하고 있습니다. 필자는 이미 memoise를 사용하여 계산 작업을 캐싱하고 있는데, 전 세계적으로 반짝 거리고 있지만 음모 렌더링에는 약 0.75 초가 걸립니다. 이미지를 렌더링하는 데 걸리는 시간을 없애고 이미 그것을 수행하는 매끄러운 방법이 있다면 그 시간을 줄일 수 있는지 궁금합니다.

자세한 내용 :.

나는이 경우 플롯 (히트 맵을 만들 그리드를 사용하고 이상적으로 디스크가 늘 확장 메모리에 플롯을 저장으로 기반으로하는 캐싱을하고 싶은

감사합니다. ! -Abhi

+0

'? renderImage'의 예제를 보면 아이디어를 얻을 수 있습니다. 기본적으로 PNG 파일을 반환하는 메모 기능을 원합니다. renderImage를 사용하여 메모 한 함수를 호출하십시오. –

+0

감사합니다. renderImage를 통해 렌더링하는 정적 이미지의 크기를 자동으로 조절할 수있는 방법에 대한 아이디어. – Abhi

답변

4

당신이 ggplot를 사용하는 (샤이니와 함께, 내가 내기 것이다 공정한 가정입니다) 가정.

  1. grob를 저장하기 위해 빈 목록을 만듭니다 (예 : Plist). 아니, 발생
  2. 경우 그래프가 이미 저장되어
  3. 선택하면 그래프, 반짝 입력에 따라 문자열의 해시를 만들 사용자 요청, 예를 들어 hash %in% names(Plist)
  4. 예라면, 즉 그래프를 제공
  5. 그래프는
+0

빠른 답장을 보내 주셔서 감사합니다. 나는 이것에 대한 그리드를 사용하고 있습니다. 그냥 grob로 무엇을 의미하는지 궁금해하고 또한 메모리에있는 여러 개의 플롯을 저장하는 것이 비용이 많이 들고 또한 서버를 다시 시작할 때 영구적으로 캐싱을하고 싶습니다. 플롯을 디스크에 캐시하고 거기에서 렌더링하는 패키지는 무엇입니까? – Abhi

+0

또한 함수에 대한 입력을 기반으로 문자열 해시를 만들 수있는 패키지를 알고 있는지 궁금합니다. 내 경우에 편리 할 것입니다. – Abhi

+0

'grob'는 단지 '그래픽 객체'입니다. 다른 R 객체와 마찬가지로 디스크에 저장할 수 있습니다. ('? saveRDS'를 보라). 그러나 디스크에서로드하는 데는 처음부터 계산하는 것만 큼 오래 걸릴 수 있습니다. –

2
Plist[hash] <- new_graph 리카르도 Saporta에서 대답은 매우 좋은

, 해시, 예에 의한 요소의 이름을 목록에 GROB을 저장하고 나는 비슷한 문제를 해결하기 위해 무엇을 사용하지만, 나는 코드를 추가하고 싶었 솔루션입니다.

캐싱을 위해 나는 그 함수에 대한 특정 그래프의 매개 변수 목록을 해시 문자열을 작성하기 위해 입력 한 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) 
} 
0

나는 shiny modules를 사용하여 다른 하나를 추가 할 원, 아주 좋다. 다음 모듈은 plot 함수와 인수의 반응식 버전을 입력으로 사용합니다. 결국 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)) 
    ) 
    } 
)