Rigueiro Filipe
Rigueiro Filipe

Reputation: 36

Download Pdf report in Shiny

Im making a shiny app, that will create 2 plots and one table.

There are a lot of options in the select input part.

Once selected it will subset the data.frame and return with another data.frame to be analised.

It will plot accordingly and I want it to generate a report in pdf (or html) with the details of the input.

Like "Generate Report" button and give me the plot for that specific input and with the input$company.pdf (or html) name.

I have searched everywhere and I cant find out how to do this.

I also want to edit the .Rmd to be in a nicer format. With just some phrases for introduction and so on.

Here is my details.

ALL CODE

library(ggplot2)
library(prophet)
library(markdown)
library(knitr)
order <- read.csv("order.csv" , header = T, sep = ",", stringsAsFactors = F)

order$Date <- strftime(order$Date.added, format = "%Y-%m-%d")
order$Date <- as.Date(order$Date)
order$Payment.company <- as.character(order$Payment.company)

choices <- sort(unique(as.character(order$Payment.company)))





ui <- shinyUI(fluidPage(

        headerPanel("Company Order Analytics"),

        sidebarPanel(position = "left",
                     selectInput("company", "Select Company:", 
                                 choices = choices, selected = "A&E Scientific sprl", multiple = FALSE),
                     submitButton("Run"),

                     downloadButton("report", "Generate report"),


                     mainPanel(position="right",
                               tabsetPanel(
                                       tabPanel("Plot",  plotOutput("plot")),
                                       tabPanel("Table", tableOutput("table")),
                                       tabPanel("Graphic",  plotOutput("plot1"))
                               )))))

server <- shinyServer(function(input, output, session) {

        plot1 <- reactive({

                a <- subset(order, order$Payment.company == input$company)
                a$l <- log10(a$Total)
                m <- subset(a, select=c("Total", "Date"))
                colnames(m) <- c("y", "ds")
                z <- prophet(m)
                future <- make_future_dataframe(z, periods = 365)
                forecast <- predict(z, future)
                plot(z, forecast, xlab = "Date", ylab = "Value Order GBP")



        })
        plot2 <- reactive({
                a <- subset(order, order$Payment.company == input$company)
                a$l <- log10(a$Total)
                m <- subset(a, select=c("Total", "Date"))
                colnames(m) <- c("y", "ds")
                z <- prophet(m, yearly.seasonality = TRUE)
                future <- make_future_dataframe(z, periods = 365)
                forecast <- predict(z, future)
                prophet_plot_components(z, forecast)


        })

        table1 <- reactive({

                a <- subset(order, order$Payment.company == input$company)
                n <- nrow(a)
                ma <- max(a$Total)
                x  <- median(a$Total)
                t <- sum(a$Total)

                tbl1 <- data.frame("Orders"= n, "Max"=ma, "Median"=x, "Total"=t)
                return(tbl1)

        }
        )

        output$plot <- renderPlot(plot1(),width = 850, height = 425)
        output$plot1 <- renderPlot(plot2(),width = 850, height = 425)
        output$table <- renderTable(table1())

        output$report <- downloadHandler(
                # For PDF output, change this to "report.pdf"
                filename = "report.html",
                content = function(file) {
                        before processing it, in
                        .
                        tempReport <- file.path(tempdir(), "report.Rmd")
                        file.copy("report.Rmd", tempReport, overwrite = TRUE)




                        rmarkdown::render(tempReport, output_file = file,
                                          params = params,
                                          envir = new.env(parent = globalenv())
                        )
                }
        )


                })

R markdown named report_file.Rmd

---
title: "Parameterized Report for Shiny"
output: pdf_document
params:
  table: 'NULL'
  plot: 'NULL'
---

```{r}
params[["plot"]]
```

```{r}
params[["plot1"]]
```

```{r}
params[["table"]]
```

The UI and Server is all on one .R document, the .Rmd is in a different document.

I have split the UI and the server and published and still error.

Im very green in R and shiny but I try to learn by trial and error. But here i am stuck completly.

I just want it to return a nicely laid out document

Here is my session:

sessionInfo()
R version 3.4.0 (2017-04-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] bindrcpp_0.2  knitr_1.17    markdown_0.8  prophet_0.2   Rcpp_0.12.12  ggplot2_2.2.1
[7] shiny_1.0.5  

loaded via a namespace (and not attached):
 [1] compiler_3.4.0       plyr_1.8.4           bindr_0.1            bitops_1.0-6        
 [5] tools_3.4.0          digest_0.6.12        evaluate_0.10.1      jsonlite_1.5        
 [9] tibble_1.3.4         gtable_0.2.0         pkgconfig_2.0.1      rlang_0.1.2         
[13] yaml_2.1.14          gridExtra_2.2.1      extraDistr_1.8.7     stringr_1.2.0       
[17] dplyr_0.7.3          tidyselect_0.2.0     stats4_3.4.0         rprojroot_1.2       
[21] grid_3.4.0           glue_1.1.1           inline_0.3.14        R6_2.2.2            
[25] rmarkdown_1.6        rstan_2.16.2         RJSONIO_1.3-0        purrr_0.2.3         
[29] tidyr_0.7.1          magrittr_1.5         backports_1.1.0      scales_0.5.0        
[33] codetools_0.2-15     htmltools_0.3.6      StanHeaders_2.16.0-1 rsconnect_0.8.5     
[37] assertthat_0.2.0     mime_0.5             xtable_1.8-2         colorspace_1.3-2    
[41] httpuv_1.3.5         labeling_0.3         stringi_1.1.5        RCurl_1.95-4.8      
[45] lazyeval_0.2.0       munsell_0.4.3   

Thank you in advance to everyone that helps. Some heroes don't wear capes.

Best

Upvotes: 1

Views: 5307

Answers (1)

Gregor de Cillia
Gregor de Cillia

Reputation: 7695

Why passing plots as parameters might fail

Saving plots as variables is possible for ggplots and other special plot types but not for the more general "base plots" that are usually produced with the plot() function. In other words, the return value of plot() is not meaningful because drawing the plot is a side effect of the function.

x <- plot(1:10)
x
#> NULL

It is therefore necessary to "pass" these side-effects to the rmarkdown report rather than the return value.

Workaround: functions

A way to pass side-effects is functions. For this, you first definine a function that draws the plot. Then the newly defined function is passed to the Rmd-document as a parameter

draw_plot <- function() {
  plot(1:10)
}
rmarkdown::render(
  "template.Rmd",
  params = list(draw_plot = draw_plot)
)

The function can now be called inside the Rmd-document and the plot will be (re-)drawn there. Generally speaking, it is possible to pass any R object as a parameter in parameterized reports and functions (closures) are a very flexible object type for use-cases like this.

Pass objects if possible

Notice however, that some plotting libraries do allow to store plots in variables. In those cases a function is not necessary. You just need to pass the return-object of the function that generates the plot.

library(ggplot2)

gg <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
class(gg)
#> [1] "gg"     "ggplot"

rmarkdown::render(
  "template.Rmd",
  params = list(plot_object = gg)
)

Reproducible example

Here is a full app to demonstrate this setup. Make sure that the app can "find" the Report

  • Put the app and the Rmd document into the same folder
  • Invoke the app with runApp("path/to/app.R") or use the "Run App" button in RStudio.

app.R

library(shiny)

ui <- fluidPage(
  textInput("main", "main", "main"),
  plotOutput("plot"),
  downloadButton("download_button")
)

server <- function(input, output, session) {
  draw_plot <- function() {
    plot(1:10, main = input$main)
  }
  output$plot <- renderPlot({
    draw_plot()
  })
  output$download_button <- downloadHandler(
    filename = "rendered_report.pdf",
    content = function(file) {
      res <- rmarkdown::render(
        "template.Rmd",
        params = list(
          draw_plot = draw_plot
        )
      )
      file.rename(res, file)
    }
  )
}

shinyApp(ui, server)

template.Rmd

---
output: pdf_document
params:
  draw_plot: NULL
---

```{r}
if (!is.null(params$draw_plot))
  params$draw_plot()
```

Upvotes: 1

Related Questions