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 !
Related
Dear all shiny developers!
I have a question about a shiny app with a Rmarkdown report downloadable.
The app is based on this https://shiny.rstudio.com/articles/generating-reports.html, taken here as an exemple.
shinyApp(
ui = fluidPage(
sliderInput("slider", "Slider", 1, 100, 50),
downloadButton("report", "Generate report")
),
server = function(input, output) {
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.pdf",
content = function(filename) {
# 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(tempdir(), "Template.Rmd")
print(tempReport)
file.copy("Template.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(n = input$slider)
# 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).
rmarkdown::render(tempReport, output_file = filename,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
with my .Rmd document
---
title: ''
output: pdf_document
geometry: "left=2cm,right=2cm,top=1cm,bottom=2cm"
params:
n: NA
---
```{r}
# The `params` object is available in the document.
params$n
```
A plot of `r params$n` random points.
The code is running ok, the document is created but when I open it, I can see that the code within the chunk is ok but not in the inline code, see below:
However, in this exemple https://shiny.rstudio.com/gallery/download-knitr-reports.html we see that the inline code is good (I don't have the code of the Rmarkdown unfortunatelly).
I saw this subject (https://community.rstudio.com/t/embedding-shiny-with-inline-not-rendering-with-html-output/41175) that could be similar but it is html and the answer does not seem to fit.
Do you have an idea why it does not function ? Or any track to explore ?
Many thanks !!
Be careful to the file.copy function !
Thanks to the remark of Limey, I notice that the Rmarkdown that had a typo few moments ago was not updated! Careful that the file.copy is correct!
Here is the script working:
shinyApp(
ui = fluidPage(
sliderInput("slider", "Slider", 1, 100, 50),
downloadButton("report", "Generate report")
),
server = function(input, output) {
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.pdf",
content = function(filename) {
# 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(tempdir(), "rules.Rmd")
print(tempReport)
file.copy("Data/rules.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(n = input$slider)
# 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).
rmarkdown::render(tempReport, output_file = filename,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
and the Rmarkown
---
title: ''
output: pdf_document
geometry: "left=2cm,right=2cm,top=1cm,bottom=2cm"
params:
n: NA
---
```{r}
# The `params` object is available in the document.
params$n
```
A plot of `r params$n` random points.
Thanks to all of you that gave time to this subject!
I am trying to download a pdf file containing tables and plots all together in single pdf file/report using the following code, but the code is showing some warning.
can someone help me with the following code or by means of any other solution?
waiting for the response
ui.R
library(gplots)
library(reshape2)
library(plotly)
dashboardBody(
downloadButton("report_file", "Generate report")
)
server.R
shinyServer(function(session,input,output){
output$estimatesPK<-renderTable({
table()
})
output$mean_graph<-renderPlot({
plot()
})
output$log_mean_graph({
plot1()
})
output$individual_graph({
plot2()
})
output$log_individual_graph({
plot3()
})
output$T_R_Ratio_Table({
table1()
})
output$report_file <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report_file.pdf",
content = function(file) {
# before processing it,
# in
# .
tempReport <- file.path(tempdir(), "report_file.Rmd")
file.copy("report_file.Rmd", tempReport, overwrite = TRUE)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
})
report_file.Rmd
---
title: "Parameterized Report for Shiny"
output: pdf_document
params:
table: 'NULL'
plot: 'NULL'
region: ""
---
params[["estimatesPK"]]
params[["mean_graph"]]
params[["log_mean_graph"]]
params[["individual_graph"]]
params[["log_individual_graph"]]
params[["T_R_Ratio_Table"]]
I tried the above code but got the following error
Quitting from lines 11-12 (report_file.Rmd)
Warning: Error in eval: object 'params' not found
[No stack trace available]
Using the fileInput widget I set the path to a file in my R-markdown document.
The path is leading to a large file. Content of this file is required at several sections in the document. So far I load the file at each section where it is required. As it takes some time for the file to load, changing the file results in quite some loading time. I would prefer to load the file only once after the path is changed.
The following minimal example shows my current implementation where the file is loaded at each section it is used.
---
output: html_document
runtime: shiny
---
library(kableExtra)
knitr::opts_chunk$set(echo = TRUE)
fileInput("file", label = h3("File input"))
renderUI({
loaded_file <-read.csv(input$file$datapath, sep = ";", header = T)
paste(loaded_file[1,2])
})
renderUI({
loaded_file <-read.csv(input$file$datapath, sep = ";", header = T )
HTML(kable(loaded_file))
})
If you load the file into a data frame as a separate reactive expression, and then reference that expression in all the relevant UIs, I believe that will accomplish what you need. Here's a small example:
---
output: html_document
runtime: shiny
---
```{r load_file}
library(kableExtra)
library(dplyr)
knitr::opts_chunk$set(echo = TRUE)
fileInput("file", label = h3("File input"))
loaded_file_test = reactive({
if(is.element("datapath", names(input$file))) {
print("loading file now...")
read.csv(input$file$datapath, sep = ",", header = T)
}
})
```
```{r first_ui}
renderUI({
HTML(kable(loaded_file_test() %>% head(10)))
})
```
```{r second_ui}
renderUI({
HTML(kable(loaded_file_test() %>% head(10)) %>% kable_styling())
})
```
When I run the document, "loading file now..." is printed just once. I interpret that to mean the file is getting loaded only once (although I'm happy to be corrected by users with a better handle on reactivity in Shiny).
The requirement is to create a pdf-report in which the user can select each plot, clicks on copy and can insert the image in e.g., powerpoint.
I used the shiny example app to create such an pdf-report with R:
https://shiny.rstudio.com/articles/generating-reports.html
(see code below)
shinyApp(
ui = fluidPage(
sliderInput("slider", "Slider", 1, 100, 50),
downloadButton("report", "Generate report")
),
server = function(input, output) {
output$report <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "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(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
# Set up parameters to pass to Rmd document
params <- list(n = input$slider)
# 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).
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
Rmd:
---
title: "Dynamic report"
output: pdf_document
params:
n: NA
---
```{r}
# The `params` object is available in the document.
params$n
```
A plot of `params$n` random points.
```{r}
plot(rnorm(params$n), rnorm(params$n))
```
This app creates a report in which I can select only the inner part (blue selection) of the plot:
I would like to be able to select the whole plot area instead of only the inner part.
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.