I'm maintaining R code in my company that is use by multiple colleagues. I decided to convert my code into a package to make it simpler to share, maintain and document. My package is build to stay internal, be used in a close environment and is not going to be on CRAN. I'm using Rstudio and it's going relatively well but I hit a problem when building vignettes.
The problem is that my code makes very specific, long and complex analysis on very big datasets. It's therefore not possible for me to have the vignette built every time I rebuilt the package. Even less having the user do it when using devtools::install_git(build_vignettes = TRUE). I've found a solution to this problem in this nice blog (https://ropensci.org/blog/2019/12/08/precompute-vignettes/). Briefly, you add .orig after your vignettes names .Rmd so they are not identified as vignette by the build process. Then, when you are ready, you precompile your script by knitting your .Rmd.orig file with:
knitr::knit("vignettes/longexample.Rmd.orig", output = "vignettes/longexample.Rmd")
This will create a quick and easy compilable version of your vignette for your package. This works for basic document with text and figures. However, I need to enter a leaflet map into my vignette. If I use this process to create my vignette with a leaflet, I get an error:
## PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.
## PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.
## Error in path.expand(path): invalid 'path' argument
I think this is a message showing that knitr is trying to get a screenshot of my map to save it as an image. This is not what I want, I want an actual map.
Reproducible example
The vignette I wrote:
---
title: "Example"
author: "BastienFR"
date: "09/05/2022"
output: html_document
---
```{r setup, message=F, warning=FALSE}
library(leaflet)
```
## Intro
A simple and slow example of vignette with a `leaflet`
## The slow part
```{r}
time <- 2
Sys.sleep(time)
message("I've waited this long!")
```
## The leaflet
```{r}
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
```
```{r}
m
```
Then, I compile it with :
knitr::knit("c://temp//longexample.Rmd.orig", output = "c://temp//longexample.Rmd")
which produce this output:
---
title: "Example"
author: "BastienFR"
date: "09/05/2022"
output: html_document
---
```r
library(leaflet)
```
## Intro
A simple and slow example of vignette with a `leaflet`
## The slow part
```r
time <- 2
Sys.sleep(time)
message("I've waited this long!")
```
```
## I've waited this long!
```
## The leaflet
```r
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
```
```{r}
m
```
```
## PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.
## PhantomJS not found. You can install it with webshot::install_phantomjs(). If it is installed, please make sure the phantomjs executable can be found via the PATH variable.
```
```
## Error in path.expand(path): invalid 'path' argument
```
So, it's not able to pass along the leaflet into the new knit markdown file (which makes sense).
I tried to bypass this problem by saving the leaflet into a temporary file like this (in my .orig file):
```{r, include=FALSE}
saveRDS(m, "c://temp/temp_leaflet.rds")
```
This would save my map, but then I have to find a way to add the next code block in the compiled version, so it appears and it's run only there. Some way to have the code block below passed as-is by knitr.
```{r, include=FALSE}
m <- readRDS("c://temp/temp_leaflet.rds")
```
So I'm stuck. Any idea how to display a leaflet into a markdown/vignette after a precompilation?
This problem can be fix by having knitr knit "asis" the lines of code you want to knit in the second run, so when building the vignette... To do this, you can change the section:
```{r}
m
```
by:
```{r, echo=FALSE}
saveRDS(m, "c://temp/temp_leaflet.rds")
```
```{r, eval=T, results="asis", echo=FALSE}
cat("```{r, echo=FALSE, warning=FALSE} \n")
cat("library(leaflet) \n")
cat("m <- readRDS('c://temp/temp_leaflet.rds') \n")
cat("```")
```
```{r, eval=T, results="asis", echo=FALSE}
cat("```{r, echo=TRUE} \n")
cat("m \n")
cat("```")
```
Explanation
First, you save your map (or data) somewhere in an rds file. Then, you use the results="asis" code block option and the cat function to write the code block that you need rendered only the in the second compilation (when the vignettes are build). So you are actually wrapping Rmarkdown code into Rmarkdown... It's ugly and confusing, but it works. Using this approach, the render code after knitting the Rmd.orig file looks like normal Rmarkdown code:
```{r, echo=FALSE, warning=FALSE}
library(leaflet)
m <- readRDS('c://temp/temp_leaflet.rds')
```
```{r, echo=TRUE}
m
```
It will then be perfectly render in your vignettes.
The only complication now is to manage the save and read location of the rds file because markdown and vignettes can have tricky working directories.
So the final .orig file is now:
---
title: "Example"
author: "BastienFR"
date: "09/05/2022"
output: html_document
---
```{r setup, message=F, warning=FALSE}
library(leaflet)
```
## Intro
A simple and slow example of vignette with a `leaflet`
## The slow part
```{r}
time <- 2
Sys.sleep(time)
message("I've waited this long!")
```
## The leaflet
```{r}
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
```
```{r, echo=FALSE}
saveRDS(m, "c://temp/temp_leaflet.rds")
```
```{r, eval=T, results="asis", echo=FALSE}
cat("```{r, echo=FALSE, warning=FALSE} \n")
cat("library(leaflet) \n")
cat("m <- readRDS('c://temp/temp_leaflet.rds') \n")
cat("```")
```
```{r, eval=T, results="asis", echo=FALSE}
cat("```{r, echo=TRUE} \n")
cat("m \n")
cat("```")
```
I would like to include screenshots from an observable notebook in an rmarkdown rendered to pdf. Directly including code blocks that call robservable does not work, so I thought I could use the webshot package instead. The example below creates a file, test.html, that does contain the interactive notebook. However, the rendered pdf still does not show any screenshot.
---
title: "robservable and webshot"
output: pdf_document
---
```{r}
knitr::opts_chunk$set(screenshot.opts = list(delay = 5))
library("robservable")
library("webshot")
library("htmlwidgets")
library("dplyr")
```
This is a test.
```{r}
f <- "test.html"
robservable("#d3/horizontal-bar-chart", include = "chart") %>%
saveWidget(f)
```
```{r}
webshot(f)
```
I tried to create a RMarkdown file, with the default template by RStudio like below:
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
When I clicked knit, it only rendered a raw html file like below, as if no css is applied to the html.
How to fix it?
Does anybody know why R markdown generates excessive white space above each plot and how can I fix that ? Is there a knitr option to be included ? Or any chunk option maybe ?
I've provided 3 images at the bottom of this post so that you can see what I mean.
Haven't used any other chunk option than echo, warning and message and about the plot it is a basic ggplot.
Let me know in the comments if I need to provide any code example of my chunks for a better view.
Edit: here's a simple rmarkdown file generating the same excessive white space above ggplots.
---
title: "Untitled"
author: "Razvan Cretu"
date: "January 9, 2019"
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r import, echo=FALSE}
library('ggplot2')
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
ggplot(cars, aes(speed, dist))+
geom_line()
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
I would like to use non-standard fonts in a ggplot2 chart which I then embed in an rmarkdown document, which get knitted into a PDF. My current workflow is to specify the font in the chart, then knit, then run extrafonts::embed_fonts on the created PDF. My question is: can I specify directly in the rmarkdown document that fonts should be embedded in the outputted PDF?
Minimal example:
---
title: "Untitled"
output: beamer_presentation
---
```{r}
library(extrafont)
library(ggplot2)
loadfonts()
qplot(iris$Sepal.Length) + theme_light(base_family = "CM Roman")
```
knitr::knit2pdf("test.rmd")
embed_fonts("test.pdf")
If you set the graphics device to "cairo_pdf" the fonts will be embedded. You can do this for individual chunks or for the whole document using knitr::opts_chunk$set
I used a really obviously different font below so that it was clear the fonts were really being set.
The package is called "extrafont" not "extrafonts"
---
title: "Untitled"
output: beamer_presentation
---
```{r, echo=FALSE, message = FALSE}
knitr::opts_chunk$set(warning=FALSE, message=FALSE, echo = FALSE, dev = "cairo_pdf")
```
```{r}
library(extrafont)
library(ggplot2)
loadfonts()
```
##
```{r, fig.width = 5}
qplot(iris$Sepal.Length) + theme_light(base_family = "Vladimir Script")
```