I've created ShinyApp where everything works fine. I'd like to add downloadHandler to generate Markdown report that contains the chosen plot. Firstly, I upload a file into ShinyApp. Nextly, I select variables to be plotted using checkBoxInput. Next step is using dropdown list to select between Lattice/ggplot2 plot and finally I'd like to click download it and get it.
Unfortunately, every time I do try to download it I receive a blank Markdown page. It doesn't really matter what format of report will be generated. I'd like to get an appropiate logic for this task. I tried both solutions I found in a network:
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx')
)
},
content = function(file) {
src <- normalizePath('report.Rmd')
owd <- setwd(getwd())
on.exit(setwd(owd))
file.copy(src, 'report.Rmd', overwrite = TRUE)
out <- render('report.Rmd', switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
})
and
output$report <- downloadHandler(
filename = "report.html",
content = function(file) {
tempReport <- file.path(getwd(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
params <- list(graph = input$graph, colsel = input$colsel)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
So respectively I created report.rmd templates for my app to fullfill it. I tried to put a lot of things inside but none of these works. Do I miss the logic for the template?
---
title: "Untitled"
author: "user"
date: "date"
output: html_document
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r plot, echo=TRUE}
plotdata <- reactive({
d <- dataIn()[, c(req(input$colsel))]
d <- melt(d, id.vars="Numer")
})
plot1 <- reactive({
dotplot(value~Numer, data=plotdata(), auto.key = list(space="right", title="Types"), groups=variable)
})
plot2 <- reactive({
ggplot(plotdata(), aes(x=Numer, y=value, color=variable)) +
geom_point()
})
graphInput <- reactive({
switch(input$graph,
"Lattice" = plot1(),
"ggplot2" = plot2())
})
renderPlot({
graphInput()
})
})
```
Alright, I got it finally! Firstly, we need to run shinyApp using function "Run External". Secondly we don't need that mess I made in the template. Simple:
---
title: "Untitled"
author: "user"
date: "date"
output: html_document
runtime: shiny
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(shiny)
library(ggplot2)
library(lattice)
library(markdown)
```
```{r plot}
plot1()
plot2()
graphInput()
```
Where plot1(), plot2() and graphinput() represent my:
plot1 <- reactive({
dotplot(value~Numer,data=plotdata(), auto.key = list(space="right", title="WWW"), groups=variable)
})
plot2 <- reactive({
ggplot(plotdata(), aes(x=Numer, y=value, color=variable)) +
geom_point()
})
graphInput <- reactive({
switch(input$graph,
"Lattice" = plot1(),
"ggplot2" = plot2()
)
})
Related
This is a followup or more a simplification of this question Error: File header.tex not found in resource path in a rmarkdown generated pdf report from a shiny app
With this Rmarkdown code I can achieve what I want:
logo.png
report.Rmd
---
geometry: margin=20truemm
fontfamily: mathpazo
fontsize: 11pt
documentclass: article
classoption: a4paper
urlcolor: blue
output:
pdf_document:
header-includes:
- \usepackage{fancyhdr}
- \pagestyle{fancy}
- \rhead{\includegraphics[width = .05\textwidth]{logo.png}}
params:
scores: NA
---
<!-- ```{r, echo=FALSE} -->
<!-- hist(params$scores) -->
<!-- ``` -->
```{r}
hist(runif(100))
```
Getting desired output: The R logo is in the header:
Now I would like to do the same from a shiny app
For this I pass the plot as a parameter and uncomment the relevant part in the report.Rmd file
relevant part in report.Rmd file:
```{r, echo=FALSE}
hist(params$scores)
```
app.R
# Global variables can go here
n <- 200
# Define the UI
ui <- bootstrapPage(
numericInput('n', 'Number of obs', n),
plotOutput('plot'),
downloadButton('report', 'Generate Report')
)
# Define the server code
server <- function(input, output) {
output$plot <- renderPlot({
hist(runif(input$n))
})
# create markdown report ----------------------------------
output$report <- downloadHandler(
filename = "report.pdf",
content = function(file) {
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
params <- list(scores = input$n)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
Error:
! Package pdftex.def Error: File `logo.png' not found: using draft setting.
I suspect because it works locally logo.png is not found in the temporary file where shiny saves tempReport
But I don't know why this works when knitting from markdown and not when calling it from the shiny app.
I think I have been through of the relevant sites on the internet!
Many thanks!
Basically you already figured out what's the issue. Hence one approach to fix your issue would be to do copy both the report template and the logo to the same temporary directory.
# Define the server code
server <- function(input, output) {
output$plot <- renderPlot({
hist(runif(input$n))
})
# create markdown report ----------------------------------
output$report <- downloadHandler(
filename = "report.pdf",
content = function(file) {
td <- tempdir()
tempReport <- file.path(td, "report.Rmd")
tempLogo <- file.path(td, "logo.png")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
file.copy("logo.png", tempLogo, overwrite = TRUE)
params <- list(scores = input$n)
rmarkdown::render(tempReport,
output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
I have problems generating table of contents in the markdown generated by my shinyapp.
I have tried to set in the YAML toc = TRUE but it doesn't work.
the app is something like this, an interface where some data is uploaded and a markdown where some graphics are rendered.
the problem is that when generating the pdf, html or word the table of contents is not generated.
app.R
library(shiny)
library(dplyr)
library(qcc)
library(ggplot2)
library(readxl)
library(kableExtra)
library(knitr)
shinyApp(ui =
fluidPage(fileInput("file", "Cargar Datos", multiple = FALSE),
radioButtons('format', 'Formato del documento', c('PDF', 'HTML', 'Word'),inline = TRUE),
downloadButton('downloadReport')),
server = function(input, output, session){
myData <- reactive({ infile <- input$file
if(is.null(infile)) return(NULL)
data <- read_excel(infile$datapath)
data})
plotData <- function(){plot(myData}
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
))
},
content = function(file) {
src <- normalizePath('report.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)
}
)
########################################
####
})
report.Rmd
---
title: "title"
subtitle: "subtitle"
output:
toc: true
toc_depth: 4
number_sections: true
author:
- "a1"
- "a2"
date: "`r format(Sys.Date(), '%B %d, %Y')`"
params:
p1: "p1"
p2: "p2"
---
# section1
## section1.1
# section2
```{r}
plotData()
Try passing the options as arguments to the rendering function, e.g.
rmarkdown::render('report.Rmd', rmarkdown::pdf_document(toc = TRUE, toc_depth = 4, number_sections = TRUE))
answered by stefan in a comment on the question.
I have a big shiny app and I'm making a downloadable pdf with rmarkdownfrom the content in it. The problem I'm having is that all the plots are in plotlyand I haven't found how to plot 2 plots in the same row of the pdf file, in R it would be a simple subplot but it doesn't work.
This is a toy example of what I have:
shinyApp(
ui = fluidPage(
downloadButton("reporte", "Generate report"),
plotlyOutput("plotTest"),
plotlyOutput("plotHist")
),
server = function(input, output) {
library(webshot)
data = as.data.frame(rnorm(1000))
plotTest = plot_ly(y = ~rnorm(1000),type = "scatter",mode = "lines")
plotHist = plot_ly(x = ~rnorm(1000),type = "histogram")
output$plotTest = renderPlotly({plotTest})
output$plotHist = renderPlotly({plotHist})
output$reporte <- downloadHandler(
filename = "reporte.pdf",
content = function(file) {
tempReport <- file.path("C:/Users/Alejandro/Documents/test", "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
params <- list(n=plotTest,k=plotHist)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
report.Rmd:
---
title: "Ensayo Reporte"
output: pdf_document
always_allow_html: yes
params:
n: NA
k: NA
---
```{r,echo=FALSE}
library(plotly)
tmpFile <- tempfile(fileext = ".png")
export(params$n, file = tmpFile)
export(params$k, file = tmpFile)
```
Adding the ususal fig.align='center',fig.show='hold' doesn't work i'll just get: Warning: Error in : pandoc document conversion failed with error 43
I would like to download Report within Shiny App, which includes Plotly graph.
So far i have not found any answer on stackoverflow.
Till this moment im able to download the screenshot of Plotly but it appears only in my working directory and it is not sent to Rmarkdown.
Example code:
library(shiny)
library(plotly)
library(rsvg)
library(ggplot2)
d <- data.frame(X1=rnorm(50,mean=50,sd=10),X2=rnorm(50,mean=5,sd=1.5),Y=rnorm(50,mean=200,sd=25))
ui <-fluidPage(
title = 'Download report',
sidebarLayout(
sidebarPanel(
helpText(),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport'),
tags$script('
document.getElementById("downloadReport").onclick = function() {
var plotly_svg = Plotly.Snapshot.toSVG(
document.querySelectorAll(".plotly")[0]
);
Shiny.onInputChange("plotly_svg", plotly_svg);
};
')
),
mainPanel(
plotlyOutput('regPlot')
)
)
)
server <- function(input, output, session) {
output$regPlot <- renderPlotly({
p <- plot_ly(d, x = d$X1, y = d$X2,mode = "markers")
p
})
observeEvent(input$plotly_svg, priority = 10, {
png_gadget <- tempfile(fileext = ".png")
png_gadget <- "out.png"
print(png_gadget)
rsvg_png(charToRaw(input$plotly_svg), png_gadget)
})
output$downloadReport <- downloadHandler(
filename = function() {
paste('my-report', sep = '.', switch(
input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
))
},
content = function(file) {
src <- normalizePath('testreport.Rmd')
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'testreport.Rmd')
library(rmarkdown)
out <- render('testreport.Rmd', params = list(region = "Test"), switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
)
}
shinyApp(ui = ui, server = server)
and testreport.Rmd file:
---
title: "test"
output: pdf_document
params:
name: "Test"
region: 'NULL'
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
Any help would be appreciated, because there is not many sources and documentations about R Plotly.
Cheers
If out.png is downloaded to your working directory, you can modify the content function of your downloadHandler to move it to the temporary directory and add it to the report:
content = function(file) {
temp_dir <- tempdir()
tempReport <- file.path(temp_dir, 'testreport.Rmd')
tempImage <- file.path(temp_dir, 'out.png')
file.copy('testreport.Rmd', tempReport, overwrite = TRUE)
file.copy('out.png', tempImage, overwrite = TRUE)
library(rmarkdown)
out <- render(tempReport, params = list(region = "Test"), switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
Your testreport.Rmd could look like (more info here):
---
title: "test"
---
Here's the plot image.
![Plot image](out.png)
You could also pass the arguments of your plotly function in the render of your content function as explained here and use a parametrized Rmarkdown file but this only works for Html reports.
Depending on how deep you want to dive into this, I would suggest creating a .brew file with your shiny code and than you can have your user send the information to the brew file and create the plot. This would give you a static code file which is updated dynamically with new data, each time. The only draw back is that when you make changes to shiny you have to make the same changes to your brew file. The other option is to create a flex dashboard with rmarkdown using the new RStudio 1.0 which becomes a html file.
See (Create parametric R markdown documentation?) for brew example.
I am trying to build a Shiny App and host it on my company's Shiny server that takes an inputted stock code and uses it to pull data from our database and generate a series of graphs and tables in markdown(.md) or word(.doc) format. Ideally, I would have three files for this App: server, ui, and the r markdown template.
I currently have a working App that uses SWeave, but TeX files have issues rendering Chinese characters, so I would like to use RMD.
server.r:
library(knitr)
shinyServer(function(input, output) {
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'
)
})
ui.r:
library(shiny)
shinyUI(basicPage(
textInput('stockcode', 'Stock Code:', value = '600340.SH'),
downloadButton('report')
))
input.Rnw:
\documentclass{article}
\begin{document}
\SweaveOpts{concordance=TRUE}
<<initialize, echo = FALSE, results = 'hide'>>=
library(ggplot2); library(RJDBC); library(gridExtra)
Sys.setlocale("LC_CTYPE", "chinese")
o.drv <- JDBC("oracle.jdbc.OracleDriver", classPath="C:/Oracle/instantclient_11_2/ojdbc5.jar", " ")
o.con <- dbConnect(o.drv, "database_address", "database_user", "database_pw")
stockcode <- input$stockcode
x <- dbGetQuery(o.con, "some_query")
pointLinePlot <- function(df) {
plotdata <- gather(df, metric, measure, -reportDate)
ggplot() + geom_line(data = plotdata, aes(x = reportDate, y = measure, color = metric)) +
geom_point(data = plotdata, aes(x = reportDate, y = measure, color = metric)) +
theme(legend.position="bottom", legend.title = element_blank()) +
scale_color_manual(name = "", values = c("darkred", "darkgreen", "darkblue", "orange"),
breaks = unique(plotdata$metric), labels = unique(plotdata$metric))
}
data_1.1.1 <- data.frame(reportDate = x$REPORT_PERIOD,
net_assets_f = x$`TOT_ASSETS-TOT_LIAB` / 1E4,
monetary_cap_f = x$MONETARY_CAP / 1E4,
net_cash_f = (x$MONETARY_CAP - x$ST_BORROW) / 1E4)
p1 <- pointLinePlot(data_1.1.1)
#
\begin{figure}
\centering
<<fig = TRUE, echo = FALSE>>=
print(p1)
#
\caption{Here goes the caption.}
\label{fig:p1}
\end{figure}
\begin{figure}
\centering
<<fig = TRUE, echo = FALSE>>=
print(grid.table(data_1.1.1, rows = NULL))
#
\caption{Here goes the caption.}
\label{fig:p1}
\end{figure}
\end{document}
Is there any way to pass the an input from a Shiny App directly to RMD like I have in input.Rnw with SWeave (stockcode <- input$stockcode)?
You do not have to pass it to the Rmd file. When the Rmd is rendered, the variable input$stockcode is taken from the current environment just like it was with the Rnw version.
server.R
library(knitr)
library(rmarkdown)
shinyServer(function(input, output) {
output$report = downloadHandler(
filename = 'myreport.pdf',
content = function(file) {
out = render('outout.Rmd')
file.rename(out, file) # move pdf to file for downloading
},
contentType = NA
)
})
input.Rmd
---
title: "Output"
output: pdf_document
---
# Test
```{r}
print(input$stockcode)
```