R Markdown cannot find object - r

I want to output Shiny app as a PDF report. But R Markdown gives the following error "Warning: Error in eval: object 'plot2' not found".
The plot works in Shiny, I'm not too familiar with Markdown and I'm getting really frustrated since I feel like I have tried quite a few potential solutions. What am I doing wrong?
Shiny UI
library(ggplot2)
library(tidyr)
library(DBI)
library(RODBCext)
library(shiny)
library(knitr)
library(kableExtra)
ui <- fluidPage(
pageWithSidebar(
headerPanel(""),
sidebarPanel(
textInput("Table", ""),
downloadButton("downloadData", "Download"),
submitButton(text="Submit"),
mainPanel(
tabsetPanel(
tabPanel("Data", tableOutput("tTable"))
),
tabsetPanel(
tabPanel("Graph", plotOutput("plot1")
)
)
)
Shiney Server
server <- function(input, output, session)
{
SQLData <- reactive({
#SQL Query
})
output$tTable <- renderTable(SQLData())
output$plot1 <- renderPlot({
da <- gather(SQLData(), key=Result, 'Control', 'Sample'
)
da2 <- data.frame(da)
ggplot(da2,aes(x=Result,y=Control, color=Result))+geom_point(size = 5) + scale_y_continuous(limits = c(80, 120)) +labs(y="", x = "")})
output$downloadData <- downloadHandler(
filename = "report.pdf",
content = function(file)
{ params <- list(table = SQLData(),
plot2 = {
da <- gather(SQLData(), key=Result, 'Control', 'Sample'
)
da2 <- data.frame(da)
ggplot(da2,aes(x=Result,y=Control, color=Result))+geom_point(size = 5) + scale_y_continuous(limits = c(80, 120)) +labs(y="", x = "")})}
)
rmarkdown::render(input = "Report.Rmd",
output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
shinyApp(ui = ui, server = server)
R Markdown Report
---
title: "Report"
output: pdf_document
header-includes:
- \usepackage{float}
- \usepackage{booktabs}
- \usepackage{makecell}
params:
table: NA
plot2: NA
---
```{r echo = FALSE, eval = TRUE}
kable(params$table, format="latex", booktabs=TRUE) %>%
kable_styling(latex_options="scale_down")
```{r echo = FALSE, eval = TRUE}
library(ggplot2)
print(plot2)

Related

Save reactive plot to temp directory as png from shiny app

This question is quite basic and related to some questions before How to save reactive plot as png to working directory in a shiny app
I had to change my strategy creating a plot from a shiny app in Rmarkdown.
For this I need to accomplish this simple task:
How can I save this plot to the temp folder as png?
Background: After saving to temp folder I will transfer it to R markdown to create a report.
library(shiny)
ui <- basicPage(
plotOutput("plot1"),
)
server <- function(input, output) {
output$plot1 <- renderPlot({
plot(mtcars$wt, mtcars$mpg)
})
}
shinyApp(ui, server)
Update: My original code looks like this. I can't provide a reproducible example with this because it is to complex:
How can I implement the answer by ismirsehregal to this code:
# plot: Radarplot ------
output$radar <- renderChartJSRadar({
chartJSRadar(PSA_13()[,c(1,2,6)],
main = "XXX",
maxScale = 100, scaleStepWidth = 10, scaleStartValue = 0, labelSize = 12,
addDots = TRUE, showToolTipLabel = TRUE, showLegend = TRUE, lineAlpha = 0.8,
polyAlpha = 0.2, responsive = FALSE,
colMatrix = col2rgb(c("orange", "navy" ,"grey")))
})
# create markdown report with radar plot ----------------------------------
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 = PSA_13()[,c(1,2,6)])
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
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
plot_object: NA
---
\pagenumbering{gobble}
```{r setup, include=FALSE}
knitr::opts_chunk$set()
library(draw)
```
```{r rectangle, echo=FALSE}
drawBox(x =1.3, y = 3.7, width = 2.5, height = 1)
```
\vspace{-80truemm}
```{r plotout, echo=FALSE, message=FALSE, out.width='100%'}
params$plot_object
```
<!-- ```{r, echo=FALSE, out.width="100%", } -->
<!-- chartJSRadar(params$scores, width = 700, height = 700, -->
<!-- main = "Peritoneal Surface Calculator Radarchart", -->
<!-- maxScale = 100, -->
<!-- scaleStepWidth = 10, -->
<!-- scaleStartValue = 0, -->
<!-- labelSize = 14, -->
<!-- addDots = TRUE, -->
<!-- showToolTipLabel = FALSE, -->
<!-- showLegend = TRUE, -->
<!-- lineAlpha = 0.8, -->
<!-- polyAlpha = 0.2, -->
<!-- responsive = FALSE, -->
<!-- colMatrix = col2rgb(c("orange", "navy" ,"grey"))) -->
<!-- ``` -->
I feel quite near to the solution and I am very grateful for your time!
There is no need to save a temporary png file. We can use recordPlot instead:
library(shiny)
library(datasets)
writeLines(con = "report.Rmd", text = "---
title: 'Plot report'
output: html_document
params:
plot_object: NA
---
```{r plotout, echo=FALSE, message=FALSE, out.width='100%'}
params$plot_object
```")
ui = fluidPage(
plotOutput("plot1"),
downloadButton("report_button", "Generate report")
)
server = function(input, output, session) {
reactivePlot1 <- reactive({
plot(mtcars$wt, mtcars$mpg)
recordPlot()
})
output$plot1 <- renderPlot({
reactivePlot1()
})
output$report_button <- downloadHandler(
filename = "report.html",
content = function(file) {
tempReport <- tempfile(fileext = ".Rmd") # make sure to avoid conflicts with other shiny sessions if more params are used
file.copy("report.Rmd", tempReport, overwrite = TRUE)
rmarkdown::render(tempReport, output_format = "html_document", output_file = file, output_options = list(self_contained = TRUE),
params = list(plot_object = reactivePlot1())
)
}
)
}
shinyApp(ui, server)
Please see my related answer here.
After OPs update - using dummy data:
app.R:
library(shiny)
library(radarchart)
scores <- data.frame("Label"=c("Communicator", "Data Wangler", "Programmer",
"Technologist", "Modeller", "Visualizer"),
"Rich" = c(9, 7, 4, 5, 3, 7),
"Andy" = c(7, 6, 6, 2, 6, 9),
"Aimee" = c(6, 5, 8, 4, 7, 6))
ui = fluidPage(
chartJSRadarOutput("radar", width = "450", height = "300"),
downloadButton("report", "Generate report")
)
server = function(input, output, session) {
reactiveRadar <- reactive({
chartJSRadar(scores, maxScale = 10, showToolTipLabel=TRUE)
})
# plot: Radarplot ------
output$radar <- renderChartJSRadar({
reactiveRadar()
})
# create markdown report with radar plot ----------------------------------
output$report <- downloadHandler(
filename = "report.html",
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 = "Test", plot_object = reactiveRadar()) # scores = PSA_13()[,c(1,2,6)]
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}
shinyApp(ui, server)
report.Rmd:
---
geometry: margin=20truemm
fontfamily: mathpazo
fontsize: 11pt
documentclass: article
classoption: a4paper
urlcolor: blue
output:
html_document
header-includes:
- \usepackage{fancyhdr}
- \pagestyle{fancy}
# - \rhead{\includegraphics[width = .05\textwidth]{logo.png}}
params:
scores: NA
plot_object: NA
---
\pagenumbering{gobble}
```{r setup, include=FALSE}
knitr::opts_chunk$set()
library(draw)
```
```{r rectangle, echo=FALSE}
drawBox(x =1.3, y = 3.7, width = 2.5, height = 1)
```
\vspace{-80truemm}
```{r plotout, echo=FALSE, message=FALSE, out.width='100%'}
params$plot_object
```
There are multiple options here.
In your case you could go with a simple option like this:
library(shiny)
ui <- basicPage(
plotOutput("plot1"),
actionButton("save", "Click to save")
)
server <- function(input, output) {
output$plot1 <- renderPlot({
plot(mtcars$wt, mtcars$mpg)
})
observeEvent("save", {
png('C:/path/to/your_plot/plot_saved.png')
plot(mtcars$wt, mtcars$mpg)
dev.off()
})
}
shinyApp(ui, server)
If you want to specify size, resolution, etc. you will have to customize the code within the observeEvent

Flexdashboard into Shiny

I am trying to adapt the RMarkdown file with *.rmd extension into Shiny application. My file has elements of Shiny but works with flexdashboard. Below you can see the code.
---
title: "Test"
author: " "
output:
flexdashboard::flex_dashboard:
orientation: columns
social: menu
source_code: embed
runtime: shiny
editor_options:
markdown:
wrap: 72
---
# Module 1
```{r global, include=FALSE}
library(biclust)
data(BicatYeast)
set.seed(1)
res <- biclust(BicatYeast, method=BCPlaid(), verbose=FALSE)
```
## Inputs {.sidebar}
```{r}
selectInput("clusterNum", label = h3("Cluster number"),
choices = list("1" = 1, "2" = 2),
selected = 1)
```
## Row {.tabset}
### Parallel Coordinates
```{r}
num <- reactive(as.integer(input$clusterNum))
renderPlot(
parallelCoordinates(BicatYeast, res, number=num()))
```
### Data for Selected Cluster
```{r}
renderTable(
BicatYeast[which(res#RowxNumber[, num()]), which(res#NumberxCol[num(), ])]
)
```
The shiny app usually has two main parts first is ui and second is server, so can anybody help how to solve this problem and run this file as a Shiny app.
library(shiny)
library(biclust)
ui <- fluidPage(
selectInput("clusterNum",
label = h3("Cluster number"),
choices = list("1" = 1, "2" = 2),
selected = 1
),
plotOutput("plot"),
tableOutput("table")
)
server <- function(input, output, session) {
set.seed(1)
data(BicatYeast)
res <- biclust(BicatYeast, method = BCPlaid(), verbose = FALSE)
num <- reactive(as.integer(input$clusterNum))
output$plot <-
renderPlot(
parallelCoordinates(BicatYeast, res, number = num())
)
output$table <-
renderTable(
BicatYeast[which(res#RowxNumber[, num()]), which(res#NumberxCol[num(), ])]
)
}
shinyApp(ui, server)

Render rmarkdown to character variable

I am fairly new to R markdown. I have built an app that requires the user to provide multiple inputs to generate a table, which can then be saved locally.
I have been now asked to implement a sort of report to list all the variables inserted by the user (in a sort of formatted document), so that before generating the table one can review all the settings and change them in case of errors.
To avoid major UI restructure, I thought about using a r markdown document and visualize it inside a modal. My problem is that rmarkdown::render renders to an output, while bs_modal takes for the argument body a character (HTML) variable.
Is there a way to make this work? Or are there better way to accomplish this?
A minimal example:
my .Rmd
---
title: "Dynamic report"
output:
html_document: default
pdf_document: default
params:
n : NA
---
A plot of `r params$n` random points.
```{r, echo=FALSE}
plot(rnorm(params$n), rnorm(params$n))
```
My App.R
library(shiny)
library(bsplus)
library(rmarkdown)
shinyApp(
ui = fluidPage(
selectInput(
inputId = "numb",
label = "Label with modal help",
choices = 50:100
),
actionButton(inputId = "mysheet",
label = "Open modal") %>% bs_attach_modal(id_modal = "modal1"),
textOutput("result")
),
server = function(input, output) {
observeEvent(input$mysheet, {
params <- input$numb
md_out <-
rmarkdown::render(
"report.Rmd",
params = params,
envir = new.env(parent = globalenv())
)
bs_modal(
id = "modal1",
title = "Equations",
body = md_out,
size = "medium"
)
})
output$result <- renderText({
paste("You chose:", input$numb)
})
}
)
bs_modal does not work like this, it must be in the UI. Below is a solution using the classical Shiny modal, no bsplus or other package.
library(shiny)
shinyApp(
ui = fluidPage(
selectInput(
inputId = "numb",
label = "Label with modal help",
choices = 50:100
),
actionButton(inputId = "mysheet",
label = "Open modal"),
textOutput("result")
),
server = function(input, output) {
observeEvent(input$mysheet, {
params <- list(n = input$numb)
md_out <-
rmarkdown::render(
"report.Rmd",
params = params,
envir = new.env(parent = globalenv())
)
showModal(modalDialog(
includeHTML(md_out),
title = "Equations",
size = "m"
))
})
output$result <- renderText({
paste("You chose:", input$numb)
})
}
)
Use html_fragment as the Rmd output:
---
title: "Dynamic report"
output:
html_fragment
params:
n : NA
---
A plot of `r params$n` random points.
```{r, echo=FALSE}
plot(rnorm(params$n), rnorm(params$n))
```

R Shiny: Compiling RMarkdown Documents with Download Buttons in Data Table

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

Image slideshow in R Shiny

I am still learning R and thus would request the experts in this platform to help me out.
I am trying to create a slideshow of .jpg images in a panel in Shiny. The below code when I run in RStudio gives me the slideshow in the Plot window of RStudio.
folder <- "D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/"
file_list <- list.files(path=folder, pattern="*.jpg", full.names = TRUE)
for (j in 1:30) {
myJPG <- stack(file_list[[j]])
plotRGB(myJPG)
}
But, when I try to put the same code in server.R and try to call through ui.R, I don't get the slideshow or any image getting displayed. I am getting a blank page when I click on the tab "Photo Slides". I tried using renderUI, renderImage and renderPlot but none works.
ui.R
tabPanel("Photo Slides",
plotOutput("trvImg")
),
server.R
output$trvImg <- renderPlot({
folder <- "D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/"
file_list <- list.files(path=folder, pattern="*.jpg", full.names = TRUE)
for (j in 1:30) {
myJPG <- stack(file_list[[j]])
plotRGB(myJPG)
}
As a learner, I am sure I'm going wrong somewhere and thus seek your help.
Thanks
Another solution, with the slickR package (based on the slick javascript library).
library(shiny)
library(slickR)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
####
),
mainPanel(
slickROutput("slickr", width="500px")
)
)
)
server <- function(input, output) {
output$slickr <- renderSlickR({
imgs <- list.files("D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/", pattern=".png", full.names = TRUE)
slickR(imgs)
})
}
# Run the application
shinyApp(ui = ui, server = server)
library(shiny)
imgs <- list.files("D:/Photos/Foreign Trips/2014_07_08_USA_Irvine/JulyAugust/", pattern=".png", full.names = TRUE)
ui <- fluidPage(
titlePanel("Slideshow"),
sidebarLayout(
sidebarPanel(
actionButton("previous", "Previous"),
actionButton("next", "Next")
),
mainPanel(
imageOutput("image")
)
)
)
server <- function(input, output, session) {
index <- reactiveVal(1)
observeEvent(input[["previous"]], {
index(max(index()-1, 1))
})
observeEvent(input[["next"]], {
index(min(index()+1, length(imgs)))
})
output$image <- renderImage({
x <- imgs[index()]
list(src = x, alt = "alternate text")
}, deleteFile = FALSE)
}
# Run the application
shinyApp(ui = ui, server = server)
If you want the buttons below the image, you can do:
sidebarLayout(
sidebarPanel(
# actionButton("previous", "Previous"),
# actionButton("next", "Next")
),
mainPanel(
imageOutput("image"),
fluidRow(
column(1, offset=1, actionButton("previous", "Previous")),
column(1, offset=1, actionButton("next", "Next"))
)
)
)
I wanted to do the same, but needed a static html output so couldn't use Shiny. I created a simple revealjs presentation and then included this in the flexdashboard as an iframe.
revealjs:
---
title:
output:
revealjs::revealjs_presentation:
transition: convex
reveal_options:
loop: true
autoSlide: 3000
keyboard: false
progress: false
shuffle: true
embedded: true
---
```{r setup, include=FALSE}
library(tidyverse)
library(glue)
library(pander)
```
```{r echo = FALSE, results ='asis'}
files <- list.files(path="./path/to/dir", full.names = TRUE)
headers <- lapply(files,
function(f){glue("{data-background='{{f}}'}",
.open = "{{",
.close = "}}")
})
pandoc.header(headers, 2)
```
Then in my flexdashboard I added:
```{r}
tags$iframe(style = "height:400px; width:100%; scrolling=yes",
src ="./imageSlider.html")
```

Resources