I'm working on a RMarkdown document that uses objects that take a long time to create and transform. The syntax is similar to this:
---
title: "Example"
author: "Test"
date: "October 29, 2015"
output: pdf_document
---
Example
```{r}
test_exc <- "NO"
if(exists("some_dta") == FALSE) {
set.seed(1)
# This data is big and messy to transform and I don't want to do it twice
some_dta <- data.frame(speed=runif(n = 1000),nonsense=runif(1000))
test_exc <- "YES"
}
```
You can also embed plots, for example:
```{r, echo=FALSE}
plot(some_dta)
```
Was the code executed: `r test_exc`
As suggested in the code above I would like to avoid repeated execution of the code if(exists("some_dta") == FALSE) { ... }. As illustrated in the code below the code within the loop executes:
I would like to know if there is a way of forcing RStudio markdown creation mechanism to understand that I those objects exists somewhere and there is no need to create them again.
You might want to use caching, as described in the online knitr documentation, e.g.:
---
title: "Example"
author: "Test"
date: "October 29, 2015"
output: pdf_document
---
Example
```{r chunk1,cache=TRUE}
set.seed(1)
# This data is big and messy to transform and I don't want to do it twice
some_dta <- data.frame(speed=runif(n = 1000),nonsense=runif(1000))
}
```
You could save your data to an .rds object and then run a check to see if that file exists
```{r}
if(!file.exists("some_dta.rds")) {
set.seed(1)
# This data is big and messy to transform and I don't want to do it twice
some_dta <- data.frame(speed=runif(n = 1000),nonsense=runif(1000))
saveRDS(some_dta, file='some_dta.rds')
} else {
some_dta <- readRDS('some_dta.rds')
}
```
Related
I am making my code more modular and would like to run multiple RMarkdown files from one overall RMarkdown. I believe I could do this if I translated all my RMarkdown files to .R scripts and used source(), but I like the document-like nature of RMarkdown and I can describe what I'm doing as I'm doing it in plain text.
The goal is to wrangle data and export a usable .sav file. I want to run clean.rmd from run.rmd, but I don't want any HTML/pdf/etc. output. Removing the output line in the YAML header doesn't prevent output. If there is a way to do this without translating everything to .R scripts, I would be very appreciative. Thank you.
clean.rmd: Script that does the cleaning
---
title: "clean"
author: "jrcalabrese"
date: "12/30/2021"
output: html_document
---
```{r}
library(tidyverse)
library(haven)
```
```{r}
data(cars)
cars <- cars %>%
mutate(newvar = speed + dist)
```
```{r}
write_spss(cars, "~/Documents/cars_new.sav", compress = FALSE)
```
run.rmd: Script that runs clean.rmd
---
title: "run"
author: "jrcalabrese"
date: "12/30/2021"
output: html_document
---
```{r}
rmarkdown::render("~/Documents/clean.rmd")
```
Thank you for your help! This function works:
---
title: "run"
author: "jrcalabrese"
date: "12/30/2021"
#output: html_document
---
```{r}
source_rmd = function(file, ...) {
tmp_file = tempfile(fileext=".R")
on.exit(unlink(tmp_file), add = TRUE)
knitr::purl(file, output=tmp_file)
source(file = tmp_file, ...)
}
```
```{r}
source_rmd("~/Documents/clean.rmd")
```
I have code similar to the following, which is dynamically generated and stored in a variable:
---
title: "test"
author: "me"
date: "3 June 2019"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, comment=""}
for (i in 1 : 3) {
cat('\n')
print(summary(iris[i*50 : 50, "Sepal.Length"] ))
}
```
Let's say it's stored in a variable named rmkdown_code
Now, I need to be able to execute the code in this variable and render it as html or pdf. I am aware of the results = asis options, and I've tried different variations of it. But still, I'm not able to get the above code to render in html. The html page comes up in rstudio, and it shows the contents of rmkdown_code variable. It's just not executing it.
I need the content of rmkdown_code to be rendered as though it was from a flat file.
I have tried the following, none of which worked. Some formatted the text better, but the graph is not plotted. I would like to avoid writing the content of the rmkdown_code variable to a flat file.
```{r,echo=FALSE,eval=TRUE}
knitr::knit_expand(text=rmkdown_code)
#eval(parse(text = rmkdown_code))
#eval(c(paste0("- `", rmkdown_code, "`"), sep = "\n"))
#eval(knitr::asis_output(rmkdown_code))
#res <- knitr::knit_expand(text=rmkdown_code);knitr::knit(text=res, quiet=F)
# knitr::inline_expr("2+2")
```
output of dput(rmarkdown):
## "---\ntitle: \"test\"\nauthor: \"me\"\ndate: \"3 June 2019\"\noutput: html_document\n---\n\n```{r setup, include=FALSE}\nknitr::opts_chunk$set(echo = TRUE)\n```\n\n```{r, comment=\"\"}\nfor (i in 1 : 3) { \n cat('\\n') \n print(summary(iris[i*50 : 50, \"Sepal.Length\"] ))\n}\n```\n"
Here's a solution, not sure if it's ideal for your use case but it does successfully render rmkdown_code as an HTML report.
Be sure that you set your working directory or are working in a project, because the .rmd will render to your current wd.
rmkdown_code <- "---\ntitle: \"test\"\nauthor: \"me\"\ndate: \"3 June 2019\"\noutput: html_document\n---\n\n```{r setup, include=FALSE}\nknitr::opts_chunk$set(echo = TRUE)\n```\n\n```{r, comment=\"\"}\nfor (i in 1 : 3) { \n cat('\\n') \n print(summary(iris[i*50 : 50, \"Sepal.Length\"] ))\n}\n```\n"
render_func <- function(x){
writeLines(x, "temp.rmd")
rmarkdown::render("temp.rmd")
}
render_func(rmkdown_code)
This gives us:
I use this rmd:
---
title: "Some Title"
author: "Some Author"
date: "`r format(Sys.time(), '%d-%m-%Y')`"
---
## A function that generates sections
```{r setup, include = FALSE}
library(pander)
create_section <- function() {
# Inserts "## Title (auto)"
pander::pandoc.header('Title (auto)', level = 2)
# Section contents
# e.g. a random plot
plot(sample(1000, 10))
# a list, formatted as Markdown
# adding also empty lines, to be sure that this is valid Markdown
pander::pandoc.p('')
pander::pandoc.list(letters[1:3])
pander::pandoc.p('')
}
```
## Generate sections
```{r, results='asis', echo=FALSE}
n_sections <- 3
for (i in seq(n_sections)) {
create_section()
}
```
and then:
library(knitr);
library(rmarkdown);
setwd("C:/bla")
knit('test_md.Rmd')
rmarkdown::pandoc_convert("test_md.md", to = "pdf", output = "test_pdf.pdf")
This kind of works but the plots are all rendered after the sections:
Each section should contain the plot. Any ideas? Thanks!
PS:
Wrapping:
plot(sample(1000, 10))
in print:
print(plot(sample(1000, 10)))
forces output to be produced. Unfortunately, NULL is also printed underneath the plot.
Could you just add pdf_document in the YAML and then generate the PDF by knitting?
---
title: "Some Title"
author: "Some Author"
date: "`r format(Sys.time(), '%d-%m-%Y')`"
output: pdf_document
---
I was able to get the same result you described when running the rmarkdown::pandoc_convert() on the .md file, all the plots at the end of the .PDF file.
I'm trying to create multiple tables using kable from a csv file, but the requirement is that I need to also put an image in the table as per the below image. The entire image needs to be in the left column. Is this possible?
The dataframe looks like this:
df<-data.frame(Amount= c('$25', '$45', '$75'),
Rate = c('1%', '1%', '3%'),
Location = c('Germany', 'Switzerland', 'England'),
ImageName= c('GE.png', 'BE.png', 'CE.png'),
Status = c('Sold','Unsold','Sold')
)
So far my R code is
---
output:
word_document:
reference_docx: ReferenceDoc.docx
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
df<-read.csv('Productdata.csv')
```
```{r loops, echo=F, results='asis'}
library(knitr)
for (i in 1:nrow(df))
{
print(kable(df[i,]))
}
```
Im really not sure how I can enter an image like that in my RMarkdown for WORD.
Here's an approach using kable, along with kableExtra functions to take care of some of the formatting. So far, I've only been able to render this properly to html. I'll update if I can make this work in Word. In the code below, I used some images I happened to have lying around. Just run the same sprintf function on your original ImageName column to get the appropriate rmarkdown tagging for your images.
---
output:
html_document:
df_print: paged
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, warning=FALSE, message=FALSE)
library(knitr)
library(kableExtra)
library(tidyverse)
#df<-read.csv('Productdata.csv')
df<-data.frame(Amount= c('$25', '$45', '$75'),
Rate = c('1%', '1%', '3%'),
Location = c('Germany', 'Switzerland', 'England'),
ImageName= c('GE.png', 'BE.png', 'CE.png'),
Status = c('Sold','Unsold','Sold')
)
# Change to names of my local images
df$ImageName =c("mal2.jpg",
"serenity2.jpg",
"blue_sun2.jpg")
# Add appropriate rmarkdown tagging
df$ImageName = sprintf("![](%s)", df$ImageName)
```
```{r loops, echo=F, results="asis"}
for (i in 1:nrow(df)) {
# Select desired row
d = df[i, ]
# Change name of ImageName column to Status value
names(d)[grep("ImageName", names(d))] = as.character(d[["Status"]])
# Convert data to "long" format
d = d %>%
select(-Status) %>%
gather(Product, value, Amount:Location) %>%
rename(` ` = value)
# Render table using kableExtra for formatting
print(kable(d, format="html") %>%
kable_styling(full_width=FALSE) %>%
collapse_rows(columns=1, valign="top"))
}
```
And here's what the html output file looks like:
I think this may bump up against the limits of kable, but here is a very not elegant way to do something similar with htmlTable. Notice that the images are relative to the directory you are running the Rmd from, or you can use links to URLs.
---
output:
html_document:
df_print: paged
word_document:
reference_docx: ReferenceDoc.docx
---
```{r setup, echo=FALSE, message=FALSE, warning=FALSE, results='asis'}
library(knitr)
library(dplyr)
library(magrittr)
library(htmlTable)
x <- 0
df <- data.frame( Status = c('Sold','Unsold','Sold'),
Image = c('images/fwhm1.jpg', 'images/ridges-shade.jpg', 'images/sep16-2018.jpg'),
Amount= c('$25', '$45', '$75'),
Rate = c('1%', '1%', '3%'),
Location = c('Germany', 'Switzerland', 'England')
)
df$Image <- sprintf('![](%s){width=150px}', df$Image)
for (i in 1:nrow(df)) {
x <- t(df[i,])
new.df <- data.frame(matrix(ncol=2,nrow=2))
new.df[1,1] <- paste(x[1],x[2],sep="<br>")
new.df[1,2] <- paste0(rownames(x)[3:5], ": ", x[3:5], collapse="<br>")
colnames(new.df) <- NULL
rownames(new.df) <- NULL
print( htmlTable(new.df,
css.cell="padding-left: .5em; padding-right: .5em; align: left; align: left; vertical-align: top;",
rnames=FALSE) )
}
```
Here is what it looks like:
I also opened the HTML file that was rendered in Word, and was able to shrink the images and add borders -- the table structure was retained. It looked like this:
Is is possible to hide some comments in code when kniting using knitr / R markdown? Example:
---
title: "SOSO"
author: "SO"
date: '2017-06-06'
output: pdf_document
---
```{r}
# Generate some data
rnorm(2)
## But keep this comment
```
When kniting I would like the first comment to disapear, but keep the second one somehow.
Here is a quick example of modifying the hook to change knitr behavior.
---
title: "SOSO"
author: "SO"
date: 2017-06-06
output: pdf_document
---
```{r setup-hook, echo=FALSE}
hook_in <- function(x, options) {
x <- x[!grepl("^#\\s+", x)]
paste0("```r\n",
paste0(x, collapse="\n"),
"\n```")
}
knitr::knit_hooks$set(source = hook_in)
```
```{r}
# Generate some data
# Lines that starts with `# ` will be removed from the rendered documents
rnorm(2)
## But keep this comment
## But lines that starts with `## ` will be kept
```
produces this
In fact, you can choose to show any lines of R code by passing numeric indices to the chunk option echo, e.g.
---
title: "SOSO"
author: "SO"
date: '2017-06-06'
output: pdf_document
---
```{r echo=4:7}
# Generate some data
rnorm(2)
## But keep this comment
```
See knitr documentation for more information.