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("```")
```
Related
I have two RMarkdown files. main.Rmd which is the main file which is rendered as well as example.Rmd which holds a longer example and is used elsewhere (hence it lives in its own document).
I want to include example.Rmd in the main.Rmd file with code highlighting of its RMarkdown code but the code of example.Rmd does not need to be executed, as if I set eval=FALSE and copied all code into the chunk by hand.
An example MWE is
main.Rmd
---
title: This is main.rmd
output: html_document
---
```{r}
# attempt that doesnt work
cat(readLines("example.Rmd"), sep = "\n")
```
and in example.Rmd
---
title: This is example.rmd
output: html_document
---
```{r}
# code that is not executed but shown in main.Rmd
data <- ...
```
Set eval=FALSE in the example.Rmd file and then include it in main.Rmd using child chunk option.
example.Rmd
---
title: This is example.Rmd
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(eval = FALSE)
```
```{r}
# This is from example.Rmd
x <- rnorm(10)
y <- rnorm(10)
lm(y ~ x)
```
```{r}
# some comments
print("This is from example.Rmd")
```
main.Rmd
---
title: This is main.Rmd
output:
html_document:
highlight: haddock
---
```{r example, child="example.Rmd"}
```
Edit
To show full source-code of the Rmarkdown file, one possible option could be reading that Rmd file and then cat it with chunk option comment="".
Now about the syntax highlighting; there's a chunk option class.output with which it is possible to specify a language name for which pandoc supports syntax highlighting.
You can get the list of language names for which pandoc has syntax highlighting support by running the following,
pandoc --list-highlight-languages
(Note, if you don't have pandoc installed separately, you can also use the pandoc installed with Rstudio itself. Run rmarkdown::pandoc_exec() to get the pandoc executable path)
Now, the file we are trying to include actually contains not just R code, but also markdown and yaml syntaxes. So it's a kind of mixed thing and pandoc has no syntax highlighting support out of the box for this. Still I have chosen c as syntax highlighting language just to show the possibility. (Also tried r, but syntax-highlighting is not so distinctive)
---
title: This is main.Rmd
output:
html_document:
highlight: tango
---
## Rmarkdown
```{r example, echo=FALSE, class.output="c", comment=""}
cat(readLines("example.Rmd"), sep = "\n")
```
But still if you want a specific syntax-highlighting for Rmarkdown, you can actually create one. See here from the pandoc documentation itself and also this answer on SO about this.
This is a follow-up question about this answer. I have set the knitr chunk options to output a png and pdf version of plots in a folder, as well as use the pngs in the knitted report.
However, I'd only like to keep the pdf version of the figure and discard the png file. Is there a knitr-equivalent of on.exit() to clean up the pngs after knitting? Or an option I overlooked?
With the rmarkdown document below, how do I automatically clean up the png version of the plot after knitting? (Or not produce it as a standalone file in the first place)
---
title: "Untitled"
author: "Me"
date: "21/10/2021"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(
echo = TRUE,
dev = c("png", "pdf"),
fig.path = here::here(
"figures",
gsub("\\.Rmd$", "\\\\", basename(knitr::current_input()))
)
)
```
```{r my_plot}
library(ggplot2)
ggplot(mpg, aes(displ, hwy)) +
geom_point()
```
That is not exactly what you are looking for, but manually removing eval=FALSE from the following chunk, deletes the wanted files:
```{r eval=FALSE, include=FALSE}
fList <- dir("figures")
fList <- fList[stringr::str_detect(fList,"\\.png$")]
file.remove(paste0("figures/",fList))
```
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 want to generate an Rmarkdown document with a password.
One possible solution is to encrypt the html output with encryptedRmd. I tried this:
---
title: "test"
author: "John Doe"
date: "18/11/2020"
output:
encryptedRmd::encrypted_html_document:
css: theme.css
---
```{r setup, include=FALSE}
library(leaflet)
library(plotly)
knitr::opts_chunk$set(echo = FALSE)
```
## 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}
fig <- plot_ly(data = iris, x = ~Sepal.Length, y = ~Petal.Length)
fig
```
## Map
You can also embed plots, for example:
```{r pressure, echo=FALSE}
m <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng=174.768, lat=-36.852, popup="The birthplace of R")
m # Print the map
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
The problem is that this solution appears to be designed to simpler reports than the one i need to protect eith password. As a result, the encrypted version of the html don't render properly plotly and leaflet results.
What can I do?
I am attempting to use R Markdown Notebooks (.Rmd files) in R Studio to capture notes and excercises while learning R programming. I find that any plots generated through the code chunks are being replicated in the corresponding html file correctly, however I am unable to get images to be replicated in the html.
Sample code below -
The image is a .PNG file in the working directory path.
```{r}
library(knitr)
knitr::include_graphics("MyImage.PNG")
```
This replicates the image in the R Markdown Notebook correctly, but not in the html file.
I am able to replicate the image in the html file by directly using html syntax -
<img src="MyImage.PNG" alt="MyImage">
I have looked through other questions around this topic, but could not resolve this issue through any of the solutions provided. I would be grateful if any of you can help resolve this.
Thanks!
I think this might be a bug to do with adding shiny.
I just did a quick test and it works for a normal document:
---
title: "Test"
output: html_document
---
```{r setup, include=FALSE}
library(knitr)
opts_chunk$set(echo = TRUE)
```
```{r, echo=FALSE, out.width="50%"}
include_graphics("../images/RMarkdownOutputFormats.png")
```
but when I add shiny it doesn't work anymore:
---
title: "Test"
output: html_document
runtime: shiny
---
```{r setup, include=FALSE}
library(knitr)
opts_chunk$set(echo = TRUE)
```
```{r, echo=FALSE, out.width="50%"}
include_graphics("../images/RMarkdownOutputFormats.png")
```
I had the same problem when using shiny_prerendered with a learnr tutorial... This from Yan Holtz worked for me:
library(png)
library(grid)
img <- readPNG("photos/header_stats.png")
grid.raster(img)