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
Related
I'm trying to make a reactive data table in R Shiny that has a button you can press to compile an RMarkdown document. Ultimately, I'm trying to combine the solutions from these two links:
R Shiny: Handle Action Buttons in Data Table and https://shiny.rstudio.com/articles/generating-reports.html. Here is what I have so far:
library(shiny)
library(shinyjs)
library(DT)
shinyApp(
ui <- fluidPage(
DT::dataTableOutput("data")
),
server <- function(input, output) {
useShinyjs()
shinyInput <- function(FUN, len, id, ...) {
inputs <- character(len)
for (i in seq_len(len)) {
inputs[i] <- as.character(FUN(paste0(id, i), ...))
}
inputs
}
df <- reactiveValues(data = data.frame(
Portfolio = c('Column1', 'Column2'),
Option_1 = shinyInput(downloadButton, 2, 'compile_', label = "Compile Document", onclick = 'Shiny.onInputChange(\"compile_document\", this.id)' ),
stringsAsFactors = FALSE,
row.names = 1:2
))
output$data <- DT::renderDataTable(
df$data, server = FALSE, escape = FALSE, selection = 'none', filter='top'
)
output$compile_document <- downloadHandler(
filename = "report.html",
content = function(file) {
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
params <- list(n = input$slider)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
Here is the RMarkdown document I'd like to compile:
---
title: "Dynamic report"
output: html_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))
```
The pieces all seem to be there, but I can't connect the "Compile Document" button to the download handler.
Here is a way that does not use downloadHandler.
library(shiny)
library(DT)
library(base64enc)
library(rmarkdown)
js <- '
Shiny.addCustomMessageHandler("download", function(b64){
const a = document.createElement("a");
document.body.append(a);
a.download = "report.docx";
a.href = b64;
a.click();
a.remove();
})
'
buttonHTML <- function(i){
as.character(
actionButton(
paste0("button_", i), label = "Report",
onclick = sprintf("Shiny.setInputValue('button', %d);", i)
)
)
}
dat <- data.frame(
PortFolio = c("Column 1", "Column 2")
)
dat$Action <- sapply(1:nrow(dat), buttonHTML)
ui <- fluidPage(
tags$head(tags$script(HTML(js))),
br(),
sliderInput("slider", "Sample size", min = 10, max = 50, value = 20),
br(),
DTOutput("dtable")
)
server <- function(input, output, session){
output[["dtable"]] <- renderDT({
datatable(dat, escape = -ncol(dat)-1)
})
observeEvent(input[["button"]], {
showNotification("Creating report...", type = "message")
tmpReport <- tempfile(fileext = ".Rmd")
file.copy("report.Rmd", tmpReport)
outfile <- file.path(tempdir(), "report.html")
render(tmpReport, output_file = outfile,
params = list(
data = dat[input[["button"]], -ncol(dat)],
n = input[["slider"]]
)
)
b64 <- dataURI(
file = outfile,
mime = "text/html"
)
session$sendCustomMessage("download", b64)
})
}
shinyApp(ui, server)
The rmd file:
---
title: "Dynamic report"
output: html_document
params:
data: "x"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
Row contents:
```{r}
params$data
```
A plot of `params$n` random points:
```{r}
plot(rnorm(params$n), rnorm(params$n))
```
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()
)
})
I want to use data from my shiny app as params in Rmarkdown. How can I get my data and use it. Here is my app:
library(shiny)
library(readxl)
dat2 <-read_xlsx("data/iepp_18.xlsx")
shinyApp(
ui = fluidPage(
selectInput("Ecole","Ecole", as.character(sort(unique(dat2$Nom_Ecole)))),
downloadButton("report", "Generate report")
),
server = function(input, output) {
output$report <- downloadHandler(
filename = "report.html",
content = function(file) {
tempReport <- file.path(tempdir(), "Reports.Rmd")
file.copy("Reports.Rmd", tempReport, overwrite = TRUE)
params <- list(base = input$Ecole)
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
)
And here is my Rmd yaml
title: "Dynamic report"
output: html_document
params:
base: NA
Is it not possible to subset the data in my Rmd with params$base?
``` r
data_bulletin %>%
filter(identification_nom_etablissement==params$base)
```
Is it not possible to subset with params?
Is it possible to use data from my shiny app in Rmarkdown?
Hello I have this simple shiny app which includes 3 files(ui,server,kable), in which i want to be able to produce a table with kable() after importing a csv file. I can make it work when i produce it in html but it cannot be converted to pdf. Specifically i get this error: Error : pandoc document conversion failed with error 43
#ui.r
library(shiny)
library(rmarkdown)
fluidPage(sidebarLayout(
sidebarPanel(
fileInput("file1", "Input CSV-File"),
downloadButton('downloadReport')
),
mainPanel(tableOutput("table"))
))
#server.r
function(input, output) {
output$downloadReport <- downloadHandler(
filename = "my-report.pdf",
content = function(file) {
src <- normalizePath('kable.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, 'kable.Rmd', overwrite = TRUE)
out <- render('kable.Rmd', params = list(file = input$file1$datapath))
file.rename(out, file)
}
)
output$table <- renderTable({
inFile <- req(input$file1)
read.csv(inFile$datapath)
})
}
#kable.rmd
---
params:
file: "mtcars.csv"
output: pdf_document
---
```{r echo = FALSE, message = FALSE, include = FALSE}
library(kableExtra)
library(knitr)
```
```{r nice-tab, tidy = FALSE, echo = FALSE, message = FALSE}
csvdata <- read.csv(file = params$file)
kable(csvdata, caption = 'REPORT TABLE',
booktabs = TRUE, longtable = TRUE,format = "latex", escape = FALSE) %>%
kable_styling(full_width = T, font_size = 10 ) %>%
row_spec(row = 0, bold = T, background = "gray")
```
I am trying to modify this example to add a pre-visualisation of the markdown report in the main Ui panel but I am not able to pass the parameters correctly using rmarkdown::render.
shinyApp(
ui = fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput("slider", "Slider", 1, 100, 50),
downloadButton("report", "Generate report")),
mainPanel(
uiOutput('reportUi')
)
)
),
server = function(input, output) {
output$report <- downloadHandler(
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(n = input$slider)
# Knit the document, passing in the `params` list
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
output$reportUi <- renderUI({
tempReportUi <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReportUi, overwrite = TRUE)
# Set up parameters to pass to Rmd document
paramsUi <- list(n = input$slider)
rmarkdown::render(tempReportUi, output_file = file,
params = paramsUi,
envir = new.env(parent = globalenv()))
})
}
)
report.Rmd
Here is my regression model:
```{r model, collapse=TRUE}
options(digits = 4)
fit <- lm(params$n, data = mtcars)
b <- coef(fit)
summary(fit)
```
The fitting result is $mpg = `r b[1]` + `r b[2]``r input$x`$.
Below is a scatter plot with the regression line.
```{r plot, fig.height=5}
par(mar = c(4, 4, 1, 1))
plot(regFormula(), data = mtcars, pch = 19, col = 'gray')
abline(fit, col = 'red', lwd = 2)
```