Экспорт R блестящей страницы в PDF

У меня есть большое приложение Shiny, которое имеет несколько подсказок, а затем создает таблицы и графики на основе этих входных данных. Я не использую rmarkdown или knitr или что-либо еще для форматирования вывода. Я просто использую стандартные блестящие элементы (sidebarPanel, mainPanel и т. Д.). Для графиков и таблиц я использую стандартные реактивные объекты renderPlot и renderTable. Я ищу простой способ иметь кнопку "Экспорт в PDF", которая экспортирует элементы на странице в документ PDF.

Я рассмотрел использование knitr и rmarkdown для создания документа с необычным форматированием (см. Примеры здесь и здесь). Проблема в том, что мне кажется, что мне нужно будет заново сгенерировать таблицы и графики либо в файле Rmd, либо в файле server.R внутри объекта downloadHandler, и я бы хотел этого избежать.

Есть ли способ вывести страницу в формате PDF более легко. Более конкретно, есть ли способ напрямую ссылаться на выходные таблицы и графики (т.е. выходные $ объекты) из файла Rmd, чтобы графики и таблицы не создавались дважды.

Изменить: вот несколько упрощенный код. Примечание. GetDataset() - это реактивная функция, которая запрашивает базу данных на основе входных данных. Моя цель - просто добавить кнопку "Экспорт", которая экспортирует уже созданные графики и таблицы. (Также как примечание, есть ли способ получить реактивный набор данных, который используется всеми реактивными элементами? Т.е. не нужно иметь ds <- getDataset() в каждом объекте?)

сервер

output$hist <- renderPlot({
  ds <- getDataset()
  # do data transformations

  ggplot(ds, aes(val)) +
    geom_histogram(binwidth = binSize, aes(fill = ..count..)) +
    labs(title = "val dist", x = "val", y = "Count") + 
    scale_fill_gradient("Count", low = "green", high = "red", guide = FALSE) +
    scale_x_continuous(limits = c(min(ds$val), quantile(ds$val, 0.99))) +
    geom_hline(yintercept=maxY, linetype=3)
})

output$time <- renderPlot({
  ds <- getDataset()
  # do data transformations
  ggplot(ds, aes(as.POSIXlt(unixTime, origin="1970-01-01", tz="UTC"), val), colour = val) +
    scale_y_continuous(limits = c(min(ds$val), quantile(ds$val, 0.99))) +
    labs(title = "Val Over Time", x = "Time (UTC)", y = "val (ms)") +
    geom_point(alpha = 0.3, size = 0.7) +
    geom_smooth()
})
output$stats <- renderTable({
  statsDf = getDataset()
  # do data transformations
  statsDf
})

UI

ui <- fluidPage(
  titlePanel("Results"),

  sidebarLayout(
    sidebarPanel(
      dateInput("startDateTime", "Start Date:", value = "2016-10-21"),
      textInput("startTime", "Start Time", "00:00:00"),
      br(),
      dateInput("endDateTime", "End Date:", value = "2016-10-21"),
      textInput("endTime", "End Time", value = "02:00:00"),
      br(),
      submitButton("Submit")
    ),
    mainPanel(
      tabsetPanel(type = "tabs",
                  tabPanel("Plots",
                           plotOutput("hist"),
                           plotOutput("time"),
                  tabPanel("Statistics", tableOutput("stats"))
      )
    )
  )
)

1 ответ

Решение

Прежде всего, вы должны действительно воспроизвести воспроизводимый пример, а не просто пример вашего кода. Мы должны скопировать и вставить ваш код, и он запустится.

Идея

  1. Так как вы используете ggplot2 который является королем grid графики, я думаю, что одним из простых способов сохранить графики / таблицы является использование gridExtra пакет. С помощью grid.arrange или же arrangeGrobs Вы можете сохранить ваши гробов на заранее определенное устройство. Затем downloadhandler выполнит загрузку.

  2. Чтобы не создавать заново все графики каждый раз, я думаю, что одним из решений является сохранение их в глобальной переменной, которую вы обновляете при каждом изменении графика. Вот reactiveValues прийти на помощь, чтобы хранить графики и таблицы и динамическую переменную.

Решение

ui.R

library(shiny)

shinyUI(fluidPage(

  # Application title
  titlePanel("Save ggplot plot/table without regenration"),

  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(
      downloadButton('export')
    ),

    # Show a plot of the generated distribution
    mainPanel(
      plotOutput("p1"),
      plotOutput("p2"),
      tableOutput("t1")
    )
  )
))

server.R

library(shiny)
library(ggplot2)
library(gridExtra)

shinyServer(function(input, output) {
  ## vals will contain all plot and table grobs
  vals <- reactiveValues(p1=NULL,p2=NULL,t1=NULL)

  ## Note that we store the plot grob before returning it 
  output$p1 <- renderPlot({
    vals$p1 <- qplot(speed, dist, data = cars)
    vals$p1
  })

  output$p2 <- renderPlot({
    vals$p2 <- qplot(mpg, wt, data = mtcars, colour = cyl)
    vals$p2
  })
  ## same thing for th etable grob
  output$t1 <- renderTable({
    dx <- head(mtcars)
    vals$t1 <- tableGrob(dx)
    dx
  })
  ## clicking on the export button will generate a pdf file 
  ## containing all grobs
  output$export = downloadHandler(
    filename = function() {"plots.pdf"},
    content = function(file) {
     pdf(file, onefile = TRUE)
     grid.arrange(vals$p1,vals$p2,vals$t1) 
     dev.off()
    }
  )
})
Другие вопросы по тегам