I'm trying to figure out how to use a downloadButton to download multiple content to one pdf file. I have in the ui the download button created:
downloadButton('downloadData', 'Download Data'))
and I am trying to get multiple plots and tables into one pdf file. I have in the server file the following
output$downloadData <- downloadHandler(
filename = function() {
paste('data-', Sys.Date(), '.pdf', sep=”)
}
but I think this will save multiple csv files. How do i download multiple plots and tables from renders such as
output$table<-renderTable({
P.Value<- c(lev.p,bart.p,turn.p,shap.p,jar.p,linm.p)
Test.Statistic<-c(lev.s,bart.s,turn.s,shap.s,jar.s,linm.s)
df<-data.frame(P.Value,Test.Statistic)
rownames(df, do.NULL = TRUE, prefix = "row")
rownames(df) <- c("Levene Test","Bartlett Test","Turning Point Test","Shapiro-Wilk Test","Jarque Bera Test","Linear Model Constant Drift Test")
df
})
,
output$qq.line<-renderPlot({
index<-1:length(lg.ret.vec())
model<-lm((lg.ret.vec())~ index)
plot(model,which=2,main="QQ plot of the residuals",xlab="Theoretical Quantiles")
qqline(rstandard(model),col="black")
})
,
output$histogram<-renderPlot({
hist(lg.ret(),main="Histogram of log returns",xlab="Log returns")
})
to name just a few.
You could take advantage of rmarkdown to make a report with all your plots, here is one example.
In your case you could use the following downloadHandler (code adapted from the link):
output$downloadData <- downloadHandler(
filename = function() {
paste('report', sep = '.','html')
},
content = function(file) {
src <- normalizePath('report.Rmd')
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd')
library(rmarkdown)
out <- render('report.Rmd',html_document())
file.rename(out, file)
}
)
And create a file called report.Rmd in the same folder as your server.R and ui.R:
report.Rmd
---
title: "Your report"
output: html_document
---
This is your plot
```{r echo=FALSE}
index<-1:length(lg.ret.vec())
model<-lm((lg.ret.vec())~ index)
plot(model,which=2,main="QQ plot of the residuals",xlab="Theoretical Quantiles")
qqline(rstandard(model),col="black")
```
This is your histogram
```{r echo=FALSE}
hist(lg.ret(),main="Histogram of log returns",xlab="Log returns")
```
you need to define content to download for downloadHandler. see http://www.inside-r.org/packages/cran/shiny/docs/downloadHandler
How do you mean you are trying to download plots and tables to a single csv file? Do you mean to merge the data? You may be confused about what a csv file is.
Related
I am trying to create a R markdown file that works with the downloadHandler in my shiny app. In the r markdown I just need a simple uiOutput. Below is how I attempted to pass it into the markdown file.
In server:
output$myOutput <- renderUI({
... # the output that needs to be printed
})
output$downloadChart <- downloadHandler(
filename = "report.pdf",
content = function(file) {
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
params <- list(report = output$myOutput)
rmarkdown::render(tempReport, output_file = file, params = params, envir = new.env(parent = globalenv()))
}
)
report.Rmd
---
title: "report"
output: pdf_document
params:
report: NA
---
```{r}
params$report```
When the code above is used, a HTML file is downloaded. I don't really understand why is this so since I already specified PDF. Is this not the right way to produce a downloadable file? I'm very new to R shiny. Any help would be appreciated!
I'm trying to make a "downloadable html report" from my shiny app, however when I deploy the app to shinyapps.io and try to download the report, it fails because I can't render the image in the R markdown file. It works fine locally, which means I think the issue is to do with the relative file path.
Short example made for ease:
app.R
library(shiny)
library(dplyr)
library(tidyverse)
library(knitr)
library(here)
#load pca plots from working directory
pca <- list.files(pattern="*pca_check.png")
#move file to www folder for it to render correctly
dir.create("www")
file.copy(pca[[1]], "www")
#pca[[1]] is "sept_2021.pca_check.png"
##################
# Make Shiny App #
##################
ui <- fluidPage(titlePanel("QC output"),
navbarPage("Menu",
tabPanel("Report",
sidebarLayout(
sidebarPanel(downloadButton("report", "Generate report"), width=0
),
mainPanel(tags$h2("Ancestry prediction Peddy"),
a(img(src=pca[[1]], height = 500, width = 300, slign="center",
target="_blank"),
href=pca[[1]])
)))))
server <- function(input, output) {
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.html",
content = function(file) {
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(pca = pca[[1]])
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
shinyApp(ui = ui, server = server)
NB: the image displays fine in the app when using this code:
a(img(src=pca[[1]], height = 500, width = 300, slign="center",
target="_blank"),
href=pca[[1]])
However, when generating the report, it fails...
report.Rmd
---
title: "Dynamic report"
output: html_document
params:
pca: NULL
---
PCA plot
```{r out.width="70%"}
knitr::include_graphics(here::here(pca))```
If it don't use here::here(pca) the code fails locally. However it's clearly giving the wrong path when deployed. So, instead I tried just:
knitr::include_graphics(pca)
That still fails when deployed. The full app is here: https://lecb.shinyapps.io/QC_sept_21/ and the image in question was successfully uploaded to https://lecb.shinyapps.io/QC_sept_21/sept_2021.pca_check.png, which implies I am referring to the correct directory... perhaps the markdown doesn't know what the "working directory" is?
Anyone have any idea how to get the image to render in the downloadable report please?
Many thanks!
knitr::rendr treats the folder where the .Rmd file sits as root. You are copying your report.Rmd to a temp folder. Thus, copying your png to the same temp folder and referencing it without here should do the trick remotely and locally:
Untested code snippet:
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.html",
content = function(file) {
tmp_dir <- tempdir()
tempReport <- file.path(tmp_dir, "report.Rmd")
tmp_pic <- file.path(tmp_dir, pca[[1]])
file.copy("report.Rmd", tempReport, overwrite = TRUE)
file.copy(pca[[1]], tmp_pic, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(pca = pca[[1]])
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
and
---
title: "Dynamic report"
output: html_document
params:
pca: NULL
---
PCA plot
```{r out.width="70%"}
knitr::include_graphics(params$pca)
```
I have a rmarkdown file which is built around the {pagedreport} package (an add-on to pagedown). This creates a html and them uses pagedown::chrome_print to convert the html to pdf.
The rmarkdown file i have works as planned when I have the parameters manually entered on the rmarkdown file, but I want to be able to pick my parameters from a shiny app.
I currently have tried this approach
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "new_report.pdf",
content = function(file) {
# Copy the report file to a temporary directory before processing it, in
# case we don't have write permissions to the current working dir (which
# can happen when deployed).
tempReport <- file.path("../temp/", "myRmarkdown.Rmd")
file.copy("myRmarkdown.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(A = input$A, B = input$B)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
library(rmarkdown)
render(tempReport, params = params,
envir = new.env(parent = globalenv()))
}
and I get the result:
Output created: MyRmarkdown.html
but there is no pdf created. Pagedown uses chrome_print to convert - and this is in the yaml of the Rmarkdown.
This is the YAML of my Rmarkdown file
output:
pagedreport::paged_windmill:
img_to_dark: TRUE
logo_to_white: TRUE
knit: pagedown::chrome_print
#toc: TRUE
toc-title: "Table of Contents"
#toc_depth: 1
main-color: "#264653"
secondary-color: "#2a9d8f"
google-font: TRUE
main-font: "Raleway"
header-font: "Roboto"
params:
A: NA
B: NA
editor_options:
markdown:
wrap: 72
I know there is an issue between shiny and chrome_print() where you need to add chrome_print(..., async = TRUE), but I don't know where to put this argument in my shiny app?
I am pretty sure you have to make sure that your render function creates a file at the location given by the argument file. In your current appraoch render uses defaults, which won't work. Thus, it should be as simple as adding the output_file argument to render. The following code snippets works for me:
test.Rmd
---
title: "Untitled"
output: html_document
params:
title: "Test"
heading: "Header"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
```{r results="asis"}
cat("## ", params$title)
```
You passed in argument `r cat(params$heading)`
app.R
library(shiny)
library(rmarkdown)
ui <- fluidPage(textInput("heading", "Heading"),
textInput("title", "Title"),
downloadButton("download_ok", "Works"),
downloadButton("download_nok", "Does not Work"))
server <- function(input, output) {
output$download_ok <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".html", sep="")
},
content = function(file) {
p <- list(title = input$title,
heading = input$heading)
render("test.Rmd", output_file = file, params = p)
}
)
output$download_nok <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".html", sep="")
},
content = function(file) {
p <- list(title = input$title,
heading = input$heading)
render("test.Rmd", params = p)
}
)
}
shinyApp(ui, server)
This snippet shows how this works now in principle, I do not know pagedreport. If there is an option in the YAML to produce pdfs right away (without the manual call to whatever function) this should work in the same way.
If you absolutely need to call the function, you can do that in the downloadHandler after the render assuming that the function can deal with input file names and create output files at the given location (again you need to create the file at the given location [as per argument file])
After reading the docs of pagedown::chrome_print you can adapt your downloadHandler as follows:
output$report <- downloadHandler(
filename = "new_report.pdf",
content = function(file) {
tempReport <- file.path("../temp/", "myRmarkdown.Rmd")
file.copy("myRmarkdown.Rmd", tempReport, overwrite = TRUE)
params <- list(A = input$A, B = input$B)
html_fn <- rmarkdown::render(tempReport, params = params,
envir = new.env(parent = globalenv()))
pagedown::chrome_print(html_fn, file)
}
I am working on a shiny app which takes user datas in input and complete first classical descriptive statistics and then a full statistical analysis. Indeed, the descriptive statistic part is done with table1 package table1 documentation used. At the end of the app I want to allow the user to download a full report containing all the plot and tables (especially descriptive statistic tables).
I am able to write some Rmarkdown scripts to include ggplots and DT datatables in the report. The problem is about the table1 object.
I render them using renderUI in the server part and uiOutput in the ui part.
Here is the code used :
Shiny script
library(shiny)
library(sas7bdat)
library(dplyr)
library(ggplot2)
library(dplyr)
library(tidyr)
library(factoextra)
library(FactoMineR)
library(corrplot)
library(cluster)
library(NbClust)
library(clValid)
library(dendextend)
library(summarytools)
library(RColorBrewer)
library(table1)
options(shiny.maxRequestSize=30*1024^2)
ui <-fluidPage(
navlistPanel(
#Welcome Page with logo and explanations
tabPanel("Welcome",textOutput("welcome_message"),textOutput("welcome_message_2"),img(src="logo_danone.jpg", height = 350, width = 350)),
#Selector for file upload
tabPanel("Input Datas",fileInput('datafile_LB', 'Choose LB Database file',
accept=c('text/csv', 'text/comma-separated-values,text/plain')),
fileInput('datafile_DS', 'Choose DS Database file',accept=c('text/csv', 'text/comma-separated-values,text/plain')),
fileInput('datafile_VS', 'Choose VS Database file',accept=c('text/csv', 'text/comma-separated-values,text/plain')),
fileInput('datafile_SV', 'Choose SV Database file',accept=c('text/csv', 'text/comma-separated-values,text/plain')),
fileInput('datafile_DM', 'Choose DM Database file',accept=c('text/csv', 'text/comma-separated-values,text/plain'))),
# Display of the input data without any modification
tabPanel("Raw Datas",
DT::dataTableOutput("filetable_LB"), radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE), downloadButton('downloadReport')
),
tabPanel("test plot", plotOutput("graph")),
tabPanel("Disposition of subjects", uiOutput("disposition"))
))
##### Server part #####
server <- function(input, output, session ) {
# Seting directory and import dependent functions
##### Input Loading #####
filedata_LB <- reactive({
infile <- input$datafile_LB
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
read.sas7bdat(infile$datapath)
})
filedata_DS <- reactive({
infile <- input$datafile_DS
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
read.sas7bdat(infile$datapath)
})
tableau <- reactive({table1(~ DSDECOD, data= filedata_DS(), topclass="Rtable1-zebra")})
#######################################################################################################################
################################# #################################
################################# Primary Endpoint Output #################################
################################# #################################
#######################################################################################################################
#This previews the CSV data file
output$filetable_LB <- DT::renderDataTable({DT::datatable(filedata_LB())})
output$graph <- renderPlot({ggplot(data = filedata_LB(), aes(y = LBSTRESN)) + geom_boxplot()})
output$disposition <- renderUI(print(table1(~ DSDECOD, data= filedata_DS(), topclass="Rtable1-zebra")))
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
))
},
content = function(file) {
src <- "C:/Users/graditse/Desktop/test_markdown/report_file.Rmd"
# temporarily switch to the temp dir, in case you do not have write
# permission to the current working directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd', overwrite = TRUE)
library(rmarkdown)
out <- render('report.Rmd', switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
)
}
shinyApp(ui, server)
Rmd script
---
title: "test"
author: "seb"
date: "26 juin 2019"
output: html_document
always_allow_html: yes
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
```{r, fig.align='center', fig.pos='htb!', echo=FALSE, cache=FALSE, warning = FALSE, message = FALSE, tidy=TRUE}
library(DT)
library(webshot)
datatable(filedata_LB(),rownames=FALSE, options = list(dom='t',ordering=F))
```
```{r, echo=FALSE}
# library(ggplot2)
# p <- ggplot(data = filedata_LB(), aes(y = LBSTRESN)) + geom_boxplot()
# p
output$graph
```
```{r, echo=False}
library(webshot)
library(table1)
library(shiny)
reactive(table1(~ DSDECOD, data= filedata_DS(), topclass="Rtable1-zebra", output = "markdown"))
```
When I try to download the report, this can't be done I got :
Warning: Error in $.shinyoutput: Reading objects from shinyoutput object not allowed.
[No stack trace available]
I don't really know how to handle this problem. This is strange because the DT table is also reactive and can be displayed into the report.
Is there a solution to display readable descriptive statistic tables into the Shiny app and in the report ?
I used the table1 package beacause it offers th possibility to process continuous and discrete variables, on different groups.
Thanks in advance !
I have an R shiny which generates a dashboard with some plots.
I implemented a download button to download the report as a PDF using knitr. Here is part the problematic part of the code:
hist_pl <- reactive({
inFile <- input$file
if (is.null(inFile))
return(NULL)
dataf <- getDF()
h <- hist(dataf)
par(new = T)
plot(x = h$mids, y=ec(h$mids)*max(h$counts), col = rgb(0,0,0,alpha=0), axes=F,xlab=NA, ylab=NA)
})
output$hist1 <- renderPlot({
hist_pl()
})
The problem is as follow:
When I comment the 'renderPlot' part of the code, the histogram appears normally in the PDF report (but not in the dashboard). When I uncomment it, the histogram disappear from the PDF (and appear in the dashboard).
The code for the download button is fairly simple:
output$report = downloadHandler(
filename = 'myreport.pdf',
content = function(file) {
out = knit2pdf('input.Rnw', clean = TRUE)
file.rename(out, file) # move pdf to file for downloading
},
contentType = 'application/pdf'
)
and the input.Rnw file:
\documentclass{article}
\begin{document}
<<names>>=
input$Val1
input$Val2
#
<<>>=
#output$mpgPlot ## N.B. This threw an error! Cannot call an object like this from shiny
print(hist_pl())
#
<<>>=
print(hist_pl())
#
\end{document}
Can someone tell me what could the problem be?