Is it possible to create user defined report from shiny app? - r

The shiny app below is taken out of gallery. It allow user to choose a variable, build a linear regression and download report.
What if I do not know in advance how many plots and models user wants to build and include into report. Is it possible to create a report with dynamically added plots?
Server.R
function(input, output) {
regFormula <- reactive({
as.formula(paste('mpg ~', input$x))
})
output$regPlot <- renderPlot({
par(mar = c(4, 4, .1, .1))
plot(regFormula(), data = mtcars, pch = 19)
})
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)
}
)
}
ui.R
fluidPage(
title = 'Download a PDF report',
sidebarLayout(
sidebarPanel(
helpText(),
selectInput('x', 'Build a regression model of mpg against:',
choices = names(mtcars)[-1]),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
plotOutput('regPlot')
)
)
)
report.Rmd
Here is my regression model:
```{r model, collapse=TRUE}
options(digits = 4)
fit <- lm(regFormula(), 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)
```

Well, it looks like I have found the answer. The problem was in local/global variables. I had to put list initialisation outside server function. Also I had to use <<- instead of <- to assign new element to the plot rather than create new plot every time.
Many thanks to Peter Ellis to support!
So, the solution is (I have slightly changed initial code to focus on the important part):
server.R
library(ggplot2); library(shiny); library(grid); library(gridExtra)
plist <- list() # IMPORTANT - outside server function
shinyServer(function(input, output) {
output$regPlot <- renderPlot({
p <- do.call("grid.arrange", c(plotList(),
ncol=floor(sqrt(length(plotList())+1)),
top = "test"))
})
plotList <- eventReactive(input$plt2rprt, {
p <- ggplot(data = mtcars, aes_string(x = input$x, y = "mpg")) +
geom_point()
# isolate(
plist[[length(plist)+1]] <<- p #IMPORTATNT <<- instead of <-
# )
return(plist)
})
output$lengthOfList <- renderText({length(plotList())})
output$lll <- renderText({length(plist)})
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(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)
}
)
}) #ShinyServer
ui.R
fluidPage(
title = 'Download a PDF report',
sidebarLayout(
sidebarPanel(
helpText(),
selectInput('x', 'Build a regression model of mpg against:',
choices = names(mtcars)[-1]),
actionButton("plt2rprt", label = "Include into report"),
hr(),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
plotOutput('regPlot'),
#verbatimTextOutput("count"),
hr(),
textOutput("lengthOfList"),
textOutput("lll"),
helpText("test-test-test")
)
)
)
report.Rmd
Length of list of plots `r length(plotList())`
```{r plot, fig.height=5}
do.call("grid.arrange", c(plotList(),
ncol=floor(sqrt(length(plotList())+1)),
top = "test"))
```

Related

Warning in normalizePath("report.Rmd") : path[1]="report.Rmd": No such file or directory

I am trying to reproduce an example form the shiny website and running into the following error. There seems to be an issue with .Rmd file. The code seems to save the report.Rmd file in temp directory but somehow it is not reading it when I try to download the plot.
Code
# load required packages
library(shiny)
library(shinydashboard)
library(tidyverse)
ui <- fluidPage(
title = 'Download a PDF report',
sidebarLayout(
sidebarPanel(
helpText(),
selectInput('x', 'Build a regression model of mpg against:',
choices = names(mtcars)[-1]),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
plotOutput('regPlot')
)
)
)
server <- function(input, output) {
regFormula <- reactive({
as.formula(paste('mpg ~', input$x))
})
output$regPlot <- renderPlot({
par(mar = c(4, 4, .1, .1))
plot(regFormula(), data = mtcars, pch = 19)
})
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)
}
)
}
shinyApp(ui, server)
Error
Listening on http://127.0.0.1:5552
Warning in normalizePath("report.Rmd") :
path[1]="report.Rmd": No such file or directory
Warning: Error in file.copy: file can not be copied both 'from' and 'to'
[No stack trace available]
Your code confused me a fair bit to be honest with you. I changed some things to get the report to download in my tempdir() successfully so hopefully this answers your question.
content = function(file) {
library(rmarkdown)
tempReport <- file.path(tempdir(), "report.Rmd")
file.copy("report.Rmd", tempReport, overwrite = TRUE)
render(tempReport, switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
}
I had to create report.Rmd file before running the above code. That works like a charm.

Rmarkdown with Rshiny

i'm trying to convert a part of my Rshiny in Rmarkdown, but when i try to run this example i get an error, how can i handle it?
this code is part of an example of Rshiny app, but when i try to run something is wrong
or could you help me to find some script to print some tables and graphs from Rshiny into Rmarkdown?
Aserver <-function(input, output) {
regFormula <- reactive({
as.formula(paste('mpg ~', input$x))
})
output$regPlot <- renderPlot({
par(mar = c(4, 4, .1, .1))
plot(regFormula(), data = mtcars, pch = 19)
})
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)
}
)
}
Aui <- fluidPage(
title = 'Download a PDF report',
sidebarLayout(
sidebarPanel(
helpText(),
selectInput('x', 'Build a regression model of mpg against:',
choices = names(mtcars)[-1]),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
plotOutput('regPlot')
)
)
)
shinyApp(Aui, Aserver)
this is the error
Warning: Error in abs_path: The file 'report.Rmd' does not exist.
[No stack trace available]
Thanks
You should distinghish two paths:
the path where the application is installed/running
the path where you are going to download the result of knitting the Markdown doc
You can get the path where the application is running with getwd().
If you don't explicitly specify a path, the report.Rmd should be located on the same directory as the application so that the application can use it.
Make sure Report.Rmd is in getwd() directory, or specify the path of Report.Rmd :
render(file.path('/custom/directory','report.Rmd'), ...

Converting shiny r markdown from downloadHandler to renderUI

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)
```

Plotly to pdf report

I'd like to add a plotly plot to a pdf file. This should be done locally (without plotly_IMAGE). Unfortunately I do not have access to webshot (since I do not have the rights to install PhantomJS). Therefore I tried a workaround described here: https://github.com/ropensci/plotly/issues/311 using shiny gadgets. But I wanted to adapt it such that the copying is doen without clicking done in the gadget.
All my attempts (see below) failed because I was not able to delay the downloadHandler until the copying was done.
Any suggestions how the dresired result (copy plotly-Image as png first and use it in pdf-Export afterwards) all done sequentially after click on Download Button?
ui:
library(shiny)
library(plotly)
library(rsvg)
shinyUI(fluidPage(
title = 'Download a PDF report',
sidebarLayout(
sidebarPanel(
helpText(),
selectInput('x', 'Build a regression model of mpg against:',
choices = names(mtcars)[-1]),
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:
library(shiny)
library(plotly)
library(rsvg)
shinyServer(function(input, output, session) {
output$regPlot <- renderPlotly({
library(plotly)
set.seed(100)
d <- diamonds[sample(nrow(diamonds), 1000), ]
print("render")
p <- plot_ly(d, x = carat, y = price, text = paste("Clarity: ", clarity),
mode = "markers", color = carat, size = carat)
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')
# 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, '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)
}
)
})

no word report creation with R & Shiny (R studio)

I created a R shiny application for stats analyses. I'd like that app allowed users to download a word report. I use the code on the shiny website gallery - http://shiny.rstudio.com/gallery/download-knitr-reports.html.
Server
shinyServer(function(input, output) {
regFormula <- reactive({
as.formula(paste('mpg ~', input$x))
})
output$regPlot <- renderPlot({
par(mar = c(4, 4, .1, .1))
plot(regFormula(), data = mtcars, pch = 19)
})
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')
library(rmarkdown)
out <- render('report.Rmd', switch(
input$format,
PDF = pdf_document(), HTML = html_document(), Word = word_document()
))
file.rename(out, file)
}
)
})
UI
library(shiny)
shinyUI(fluidPage(
title = 'Download a PDF report',
sidebarLayout(
sidebarPanel(
helpText(),
selectInput('x', 'Build a regression model of mpg against:',
choices = names(mtcars)[-1]),
radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
inline = TRUE),
downloadButton('downloadReport')
),
mainPanel(
plotOutput('regPlot')
)
)
))
It works fine and I can download the report on the web app. I use the proposed code in R studio on a OS X computer and it works fine too. I try to do the same with R studio on a win 7 computer but it doesn't works, the report (html, pdf or docx) is not created whereas the apps works fine.
Can someone help me ?
Ari

Resources