Shiny and RMarkdown: Rendering multiple chunks - shiny

I would like to create a Shiny-RMarkdown app which allows uploading own datasets. Datasets sometimes not only affect one chunk which can be re-rendered by renderPlot() (or similar) but sometimes two or more chunks. See the following example:
---
title: Render multiple chunks
output: html_document
runtime: shiny
---
```{r echo=FALSE}
library(shiny)
fileInput('file1', 'Choose your own CSV File instead of provided
data',accept=c('text/csv', 'text/comma-separated-values,text/plain',
'.csv'))
go1<-reactive({
dpath <- "CurrentBiologyData.txt"
if(!is.null(input$file1)){
dpath <- input$file1$datapath
}
CB.dat <- read.table(dpath, header = TRUE) #choose 'CurrentBiologyData.txt'
plot(CB.dat)
})
```
```{r echo=FALSE}
renderPlot({
go1()
})
```
```{r}
renderPlot({
print(CB.dat)
})
```
So I have three chunks which are affected if I upload a new dataset. The problem is that the third chunk does not see CB.dat which is filled in the first chunk:
Error: Object 'CB.dat' not found
Any ideas how I can make that work?

Applying to your example what I meant in my comment
Put the file reading in a reactive then use it wherever you need it
---
title: Render multiple chunks
output: html_document
runtime: shiny
---
```{r echo=FALSE}
library(shiny)
fileInput('file1', 'Choose your own CSV File instead of provided
data',accept=c('text/csv', 'text/comma-separated-values,text/plain',
'.csv'))
CB.dat<-reactive({
dpath <- "CurrentBiologyData.txt"
if(!is.null(input$file1)){
dpath <- input$file1$datapath
}
read.table(dpath, header = TRUE) #choose 'CurrentBiologyData.txt'
})
```
```{r echo=FALSE}
renderPlot(plot(CB.dat())
```
```{r}
renderTable(CB.dat())
```

Related

Maximize imported image on page in officer / officedown to Word (docx)

I recently tried using officedown to create a .docx report of my document. In my documents I import images from an \images folder in my project directory.
Normally when I knit a document I am able to maximize its position on the page.
Does anyone know how to do this using officedown? I have no issues when I run this code in RMarkdown
This is what I get using officedown
This is what I want (notice the image is taking up the whole page)
I have included a reprex below
---
date: "`r Sys.Date()`"
author:
title: "GitHub Example"
output:
officedown::rdocx_document
---
```{r setup, include=FALSE, echo = FALSE}
pacman::p_load(readxl, dplyr, apastats, officedown, officer, ggplot2, knitr) # load packages
knitr::opts_chunk$set(fig.align = 'center',
fig.cap = TRUE,
fig.pos = 'H',
fig.path = 'images/',
echo = FALSE,
warning = FALSE,
message = FALSE,
include = TRUE,
out.height="100%", out.width="100%",
dpi = 300)
```
```{r}
# Creating a boxplot and saving it in \images directory
plot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_boxplot()
ggsave("images/plot.png",plot, width=11, height=8.5, dpi=300)
```
## Figures
Figure \#ref(fig:boxplot) shows a boxplot that is made within the RMarkdown document.
I want to call in an image saved from a previous R scripts which is saved
in my `\images` directory shown in Figure \#ref(fig:plot). But notice how it
does not take up the whole page.
<!---BLOCK_LANDSCAPE_START--->
```{r fig.cap="A boxplot", fig.id = "boxplot"}
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_boxplot()
```
<!---BLOCK_LANDSCAPE_STOP--->
<!---BLOCK_LANDSCAPE_START--->
```{r fig.id="plot", fig.cap="boxplot imported from images folder", echo=FALSE}
knitr::include_graphics("images/plot.png")
```
<!---BLOCK_LANDSCAPE_STOP--->
You can use knitr usual parameters fig.width and fig.height (inches).
---
date: "`r Sys.Date()`"
author:
title: "GitHub Example"
output:
officedown::rdocx_document
---
```{r setup, include=FALSE, echo = FALSE}
pacman::p_load(readxl, dplyr, apastats, officedown, officer, ggplot2, knitr) # load packages
knitr::opts_chunk$set(fig.align = 'center',
echo = FALSE,
warning = FALSE,
message = FALSE,
dpi = 300)
```
```{r}
plot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_boxplot()
```
<!---BLOCK_LANDSCAPE_START--->
```{r fig.cap="A boxplot", fig.id = "boxplot"}
ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_boxplot()
```
```{r fig.width=10, fig.height=5, fig.id="plot", fig.cap="boxplot imported from images folder", echo=FALSE}
plot
```
<!---BLOCK_LANDSCAPE_STOP--->
Tips for working with plots/figures in Word output:
a) you need to use fig.height and/or fig.width to scale plots/figures;
b) consider using chunk option crop = TRUE with the function hook_pdfcrop() to trim/crop the extra white margin around the plot (see #CL. SO answer here);
c) chunk options: fig.align, fig.pos, out.height, out.width or out.extra are not supported for Word output.
To achieve desired output, you may consider the following changes:
```{r setup, include = FALSE, echo = FALSE}
pacman::p_load(readxl, dplyr, apastats, officedown, officer, ggplot2, knitr) # load packages
knitr::opts_chunk$set(fig.cap = TRUE,
fig.path = 'images/',
echo = FALSE,
warning = FALSE,
message = FALSE,
include = TRUE,
dpi = 300)
```
```{r}
# Creating a boxplot and saving it in \images directory
plot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_boxplot()
ggsave("images/plot.png", plot, dpi = 300)
```
```{r fig.id = "plot", fig.cap = "boxplot imported from images folder", fig.height = 6, fig.width = 7.5, echo = FALSE}
knitr::include_graphics("images/plot.png")
```
Does this helps somehow?
After implementing #David Gohel answer for a few projects. I still am envious of the use of out.height and out.width in PDF outputs.
In most of my projects I have resorted to going into File Explorer, right clicking on the figure in question and writing down the images dimensions to calculate its aspect ratio.
In a typical officedown project I will only call fig.width so that I can make sure the figure is maximized to the size of the page while maintaining its original aspect ratio.
knitr::include_graphics("images/plot.png")
I worked on trying to implement this automatically which would require reading the images dimensions to set fig.asp. Its not perfect, and I am sure someone else will have a much better and cleaner approach but you can accomplish this using the magick package. This also requires 2 chunks to accomplish the feat (again not optimal)
{r, eval=TRUE, echo=FALSE}
# First chunk to fetch the image size and calculate its aspect ratio
img <- magick::image_read("images/plot1.png") # read the image using the magic library
img.asp <- image_info(img)$height / image_info(img)$width # calculate the figures aspect ratio
{r fig.width=11, fig.asp = img.asp, fig.id="plot", fig.cap="boxplot imported from images folder", echo=FALSE}
# second chunk uses "img.asp" to make sure our aspect ratio is maintained.
knitr::include_graphics("images/plot.png")

Switching between output formats while generating downloadable RMarkdown reports from Shiny

I am trying to generate downloadable RMarkdown reports using Shiny. I have included radioButtons in the UI to allow the user to select the output format of the report (Word or PDF). The problem I am facing is that the format selection in the UI is not impacting the output format. The first choice in the radioButton statement is dictating the output format, i.e., currently the first choice in the list, choices=list("PDF", "Word"), is set to PDF, this is producing a PDF output regardless of what is selected in the UI. Similarly, if the first choice in the list is set to Word, choices=list("Word", "PDF"), then a Word document is the final output regardless of what is selected in the UI.
I am unsure what I doing wrong so I would really appreciate any help! I have provided some dummy code below.
Shiny UI/Server
# Load packages
suppressWarnings(suppressMessages(library(shiny)))
suppressWarnings(suppressMessages(library(tidyverse)))
suppressWarnings(suppressMessages(library(rmarkdown)))
suppressWarnings(suppressMessages(library(bookdown)))
suppressWarnings(suppressMessages(library(knitr)))
# Define data frame variables
countries = c("Canada", "United States of America", "Qatar", "Scotland", "Bangladesh")
capitals = c("Ottawa", "Washington, DC", "Doha", "Edinburgh", "Dhaka")
values = seq(1, 5, 1)
# Build data fram
df = data.frame(countries, capitals, values)
# User interface
ui = fluidPage(
# Define title for the app
titlePanel("Dummy example"),
# Sidebar layout with input and output definitions
sidebarLayout(
sidebarPanel(
selectInput("select_country", "Select Country:", choice = unique(df$countries)),
uiOutput("select_capital"),
radioButtons("format", "Summary Format:", choices=list("PDF", "Word"), inline=TRUE),
downloadButton("download_report", "Download Report")
),
mainPanel(
)
)
)
# Server logic
server = function(input, output, clientData, session) {
# Build capitals filter based on selected country
output$select_capital = renderUI({
df = df[df$countries == input$select_country, ]
choice = unique(df$capitals)
selectInput(
"select_capital",
"Select Capital:",
choices = choice
)
})
# Download report
output$download_report = downloadHandler(
filename = paste("report",
switch(input$format, "Word"="docx", "PDF"="pdf"), sep="."),
content = function(file) {
normalized_path = normalizePath("report.Rmd")
# Temporarily switch to a temp directory in case you do not have permission
# to the current working directory
owd = setwd(tempdir())
on.exit(setwd(owd))
file.copy(normalized_path, "report.Rmd", overwrite=TRUE)
# Set up parameters to pass to Rmd documents
params = list(countries = input$select_country,
capitals = input$select_capital,
format = input$format)
out = rmarkdown::render("report.Rmd",
switch(input$format, "PDF"=pdf_document(), "Word"=word_document()),
params=params,
envir=new.env())
file.rename(out, file)
}
)
}
# Run RShiny app
shinyApp(ui, server)
RMarkdown template
---
title: "Dummy example"
date: "`r format(Sys.time(), '%B %d, %Y')`"
output:
bookdown::pdf_document2:
toc: false
df_print: kable
extra_dependencies: ["float"]
bookdown::word_document2:
toc: false
classoption: twocolumn
params:
countries: NA
capitals: NA
format: NA
urlcolor: blue
always_allow_html: true
header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage{float}
- \usepackage{tabu}
---
```{r packages, echo=FALSE, eval=TRUE, message=FALSE, include=FALSE}
knitr::opts_chunk$set(fig.pos = "!H", out.extra = "")
# Load packages
library(tidyverse)
library(rmarkdown)
library(bookdown)
library(knitr)
library(flextable)
library(kableExtra)
```
```{r print-dataframe, echo=FALSE, eval=TRUE, message=FALSE, results="asis"}
# Print data frame
print(params$format)
if (params$format == "Word") {
# Use flextable if the output format is Word
flextable(df)
} else {
# Use kable if the output format if PDF
df = knitr::kable(df, booktabs=T, caption="Dummy example") %>%
kableExtra::kable_styling(latex_options=c("scale_down", "HOLD_position", "repeat_header"))
print(df)
}
```
I think the format of the rendered document is the one selected. Only the file name doesn't have the correct extension. That's because you have a reactive variable (input$format) in the filename argument of the downloadHandler. In such case, you have to use a function for filename. That is, replace
filename = paste("report", switch(input$format, "Word"="docx", "PDF"="pdf"), sep=".")
with
filename = function(){
paste("report", switch(input$format, "Word"="docx", "PDF"="pdf"), sep=".")
}

How to format reactive text output in R-Markdown?

In my Markdown file I use Shiny widgets to set some parameter. Add the end of the document some reactive text should be shown, depending on the choosen parameter, changing when a parameter is changed. This text should be formatted with linebreaks. Output format is HTML. The following minimal example shows my approach, the screenshot below the outcome. Unfortunatelly without linebreaks.
How can I archieve linebreaks in reactive textoutput in R-Markdown?
---
title: 'Minimal example'
runtime: shiny
output:
html_document
---
```{r setup, include=FALSE}
library(knitr)
library(shiny)
knitr::opts_chunk$set(echo = F)
```
```{r}
selectInput("input1", label = "Input1",
choices = 1:5, selected = 1)
selectInput("input2", label = "Input2",
choices = 1:5, selected = 1)
```
```{r}
### Generate Parameter for report
renderText({
HTML(paste('Input1:', input$input1, '<br> Input2:', input$input2))
})
renderText({
paste('Input1:', input$input1, ' \\n Input2:', input$input2)
})
renderText({
paste('Input1:', input$input1, ' \n Input2:', input$input2)
})
renderText({
cat(paste('Input1:', input$input1, ' \n Input2:', input$input2))
})
```
Use renderUI in combination with HTML() instead:
renderUI({
HTML(paste('Input1:', input$input1, '<br> Input2:', input$input2))
})

Download charts in flexdashboard

I am trying to use a download button in the input column of a flex dashboard to download a collection of charts rendered as *.pdf. The entire dashboard works just fine, and the download button renders properly; however, when I click the download button, the file that does get downloaded does not contain the intended charts. The warning I get from my Mac when it tries to open the file is that the file might be damaged or that it's a form that Preview (or Acrobat) doesn't recognize. The following is a highly redacted form of my code that contains the problematic sections. Any guidance on how to get charts to download in a flexdashboard as charts download in Shiny?
---
title: "My Model"
runtime: shiny
output:
flexdashboard::flex_dashboard:
theme: cerulean
vertical_layout: scroll
orientation: rows
---
```{r global, include=FALSE}
library(shiny)
library(shinyBS)
library(shinyWidgets)
library(flexdashboard)
library(tidyverse)
library(readxl)
library(knitr)
library(RColorBrewer)
source("MLHS_Distributions.R")
source("interp.R")
source("tooltips.R")
```
```{r Inputs}
downloadButton("downlaodReport","Price Comparision Report")
downloadHandler(filename = function() {
filename = paste0("ModelReport-", Sys.Date(), ".pdf")
},
content = function(file) {
pdf(file, width = 8.5, height = 6.14)
renderPrint({output$gg.prob.win.price()})
dev.off()
}
)
```
```{r priceProbWinChart}
renderPlot({
gg.prob.win.price <- --ggplot code--
plot(gg.prob.win.price)
})
```

Rmarkdown - how to remove grey background on output

I am experiencing a slightly irritating problem, which is that I am not able to remove the grey text from output (please see picture below).
I've searched for a solution, but is restricted by my lack of knowledge about the proper terms, and therefore I am not able to find any solutions.
I know this can be somehow bypassed by using only one "`", yet I need the triple "```" in order to run my code interpreting rows.
The grey background on output
---
title: "Untitled"
output: word_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, echo=FALSE}
hej <- ("test")
print(hej)
```
You might simply want to override the grey highlighting in the YAML header as follows:
---
title: "Untitled"
output:
word_document:
highlight: NULL
---
```{r setup, include = FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
Now if you want to get rid of the "##" and the line-numbers, tell knitr to handle texts as-is, and use cat():
```{r textfoo, echo = FALSE, results = 'asis'}
hej <- ("test")
cat(hej)
```
Et voilĂ :