I'd like to change the fig.cap chunk option within a chunk for a knitr document. I tend to write a lot of reporting code that looks like the following to take a plot out of a tibble and use the associated caption with it.
```{r fig, fig.cap=d_plot$caption}
d_plot <- [load the plotting tibble from prior work]
knit_print(d_plot$figure[[1]])
```
Something similar to what I'd like to do is the following, but where the caption actually shows up. And, better yet would be if it would modify fig.cap and fig.scap with the possibility of having multiple knit_print() calls with multiple sets of figures.
---
title: "Untitled"
author: "William Denney"
date: '2022-04-19'
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo=FALSE, warning=FALSE, error=FALSE)
library(tidyverse)
library(knitr)
```
# Test
```{r functions, include=FALSE}
knit_print.fig_n_cap <- function(x) {
lapply(x$figure, knit_print)
opts_chunk$set(fig.cap=x$caption)
}
as_fig_n_cap <- function(x) {
stopifnot(is.data.frame(x))
stopifnot("figure" %in% names(x))
stopifnot("caption" %in% names(x))
class(x) <- c("fig_n_cap", class(x))
x
}
p <- ggplot(data.frame(x=1:3, y=1:3), aes(x=x, y=y)) + geom_line()
d <- as_fig_n_cap(tibble(figure=list(p), caption="My caption"))
```
```{r}
knit_print(d)
```
I often want to print out the dataframes contained in a list as paged tables in my rmarkdown documents. Calling each dataframe individually renders the desired ouptut if the right df_print option is selected. However, the point of having a list is that the number of dataframes varies depending on the parameters passed to the rmarkdown document; so that's no real solution.
Based on Vincent Guyader's answer to this question and on this example of rmarkdown::paged_table, I've tried to do the following without success.
Is there a way to achieve this at all? I'd be happy to use any package that supports pagination remotely resembling the df_print option.
---
title: "Printing paged tables from a list of dataframes in Rmarkdown"
output:
html_document:
df_print: paged
---
```{r}
library(DT)
library(rmarkdown)
library(purrr)
library(knitr)
df_list <- list("cars" = mtcars, "flowers" = iris)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, results='asis')
```
### Desired output but impossible to generalise
```{r}
df_list[["cars"]]
```
```{r}
df_list[["flowers"]]
```
### datatable shows as blanks on the page
```{r}
map(df_list, ~DT::datatable(.x) %>%
htmltools::tagList() %>%
print())
```
### rmarkdown outputs dataframe contents as one very long string
```{r}
map(df_list, rmarkdown::paged_table)
```
The issue is that the JS dependencies needed to render the Datatable are not included in the HTML output. A workaround which I borrowed from here is to add a code chunk
```{r init-step, include=FALSE}
DT::datatable(mtcars)
```
outside of the loop or map statement which ensures that the JS dependencies are included. Also, I would recommend to switch to purrr::walk as using map has the effect that the tables are plotted twice.
---
title: "Printing paged tables from a list of dataframes in Rmarkdown"
output:
html_document:
df_print: paged
---
```{r}
library(DT)
library(rmarkdown)
library(purrr)
library(knitr)
df_list <- list("cars" = mtcars, "flowers" = iris)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, results='asis')
```
### Desired output but impossible to generalise
```{r}
df_list[["cars"]]
```
```{r}
df_list[["flowers"]]
```
### datatable shows as blanks on the page
```{r init-step, include=FALSE}
DT::datatable(mtcars)
```
```{r}
walk(df_list, ~DT::datatable(.x) %>%
htmltools::tagList() %>%
print())
```
When using results='asis' argument, the renderer (here DT) has to be initialized once before being applied on a asis list.
This seems to be a general problem, see here with leaflet, and here with Highcharter.
The answer to this general question has been given here.
In this case:
---
title: "Printing paged tables from a list of dataframes in Rmarkdown"
output:
html_document:
df_print: paged
---
```{r,}
library(DT)
library(rmarkdown)
library(purrr)
library(knitr)
df_list <- list("cars" = mtcars, "flowers" = iris)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, results='asis')
# initialize the renderer
data.frame() %>%
DT::datatable() %>%
knitr::knit_print() %>%
attr('knit_meta') %>%
knitr::knit_meta_add() %>%
invisible()
```
```{r , results='asis'}
#Remove already printed element and print the rest
df_list[[1]] <- NULL
map(df_list, ~DT::datatable(.x) %>%
htmltools::tagList() %>%
print())
```
Im new to Rmarkdown and I would like to create dynamic reports where every report section is generated from a template (child) document. Each section will then start with a newpage in the rendered pdf.
My approach is currently based on this post which shows how to generate dynamically text in the child (which works), however I am not able to transfer the contents of the loop into a R-Codeblock, probably because the params are not well defined in the way that I tried to do it.
This is how my parent document looks like:
---
title: "Dynamic RMarkdown"
output: pdf_document
---
```{r setup, include=FALSE}
library("knitr")
options(knitr.duplicate.label = "allow")
```
# Automate Chunks of Analysis in R Markdown
Blahblah Blabla
\newpage
```{r run-numeric-md, include=FALSE}
out = NULL
for (i in as.character(unique(iris$Species))) {
out = c(out, knit_expand('template.Rmd'))
params <- list(species = i)
}
```
`r paste(knit(text = out), collapse = '\n')`
and this is how the child looks like
---
title: "template"
output: html_document
params:
species: NA
---
# This is the reporting section of Species {{i}}
This is a plot of Sepal length and width based on species {{i}}.
```{r plot2}
paste(params$species)
# plot doesnt work work
# plot(iris$Sepal.Length[iris$Species=={{i}}],
# iris$Sepal.Width[iris$Species=={{i}}]
# )
```
\newpage
To my understanding the parameter that is actually passed is the last species from the dataset generated in the loop but I'm not sure why the plot would't work then. Can anybody help me out on how to fix this issue?
Ok. No need to go through params. The solution was simply to put i between brackets AND parenthesis in the child-document.
Parent:
---
title: "Dynamic RMarkdown"
output: pdf_document
---
```{r setup, include=FALSE}
library("knitr")
options(knitr.duplicate.label = "allow")
```
# Automate Chunks of Analysis in R Markdown
Blahblah Blahblah Main text before individual sections
\newpage
```{r run-numeric-md, include=FALSE}
out = NULL
for (i in as.character(unique(iris$Species))) {
out = c(out, knit_expand('template.Rmd'))
}
```
`r paste(knit(text = out), collapse = '\n')`
Child
---
title: "template"
output: html_document
---
# This is the reporting page of Species {{i}}
This is a plot of Sepal length and width based on species {{i}}.
```{r plot2}
paste("This will be a plot of Sepal Length and Witdh from", '{{i}}')
plot(iris$Sepal.Length[iris$Species=='{{i}}'],
iris$Sepal.Width[iris$Species=='{{i}}']
)
```
\newpage
Original solution found here.
I create a Leaflet widget and save it locally:
library(htmlwidgets)
library(leaflet)
library(sf)
shp = st_read("/path/to/some/shapefile.shp")
m = shp %>%
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
setView(lng = -70, lat = 40, zoom = 11)
saveWidget(m, "m.html")
Now I want to load this widget in a Rmarkdown chunk:
---
title: "Title"
author: "author"
date: "5/8/2020"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
etc etc etc
```{r}
function_that_loads_widget("m.html")
```
etc etc etc
I've tried htmltools::includeHTML() but that makes the entire HTML output one big widget. The text of the report is not displayed.
I realize I could put the the code that created the Leaflet widget directly in the Rmarkdown chunk, but I don't want to do that.
knitr::include_url() appears to be the solution. This works for my blogdown post.
```{r, out.width="100%"}
knitr::include_url("url_of_html", height="1080px")
```
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: