Looping headers/sections in rmarkdown? - r-markdown

I am trying to generate a loop with sections/headers that are followed by a figure in rmarkdown. I understand that I can use cat("## xyz") to generate a new header in my chunk but I observe some odd behaviour.
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = F)
```
Version 1: (does not work)
```{r, results='asis'}
for (i in 1:5) {
cat("\n")
cat("## This is a heading for ", i, "\n")
plot(pressure)
cat("\n")
}
```
Version 2: (does not work)
```{r, results='asis'}
for (i in 1:5) {
cat("\n")
cat("## This is a heading for ", i, "\n")
plot(pressure)
cat("\n")
plot(pressure)
cat("\n")
}
```
Version 3 (works):
```{r, results='asis'}
for (i in 1:5) {
cat("\n")
cat("## This is a heading for ", i, "\n")
plot(cars)
cat("\n")
plot(pressure)
cat("\n")
}
```
I expect the output to be
Header 1
Figure 1
Header 2
Figure 2
Header 3
Figure 3
etc.

Related

Merging column header in latex table created by kable in Rmarkdown

I have created a latex table as below using kable in Rmarkdown:
---
output: pdf_document
header-includes:
- \usepackage{xcolor}
---
```{r, message=FALSE, warning=FALSE, echo=FALSE}
library(kableExtra)
library(tidyr)
library(dplyr)
data(iris)
iris %>%
as_tibble %>%
gather(.,key = variable,value = value,-Species) %>%
group_by(Species,variable) %>%
summarise(value=mean(value)) %>%
ungroup %>%
spread(.,key = variable,value = value) %>%
mutate(`Percentage Change`=`Petal.Length`/`Petal.Width`*100) %>%
kable(.,format='latex',
align='c',linesep='',
booktabs=TRUE,escape=FALSE) %>%
add_header_above(.,c(' '=1,'Parts'=4,' '=1),
escape = FALSE) %>%
kable_styling(latex_options = c('striped','HOLD_position','scale_down'))
```
I would like to have the column header "Species" and "Percentage Change" merged with the empty space above them respectively, so that Species can be placed in the middle of the two header rows, while Percentage Change (Petal Length/ Petal Width) can occupy two rows, rather than having a empty row above, and prevent other column to have an empty row below.
Wonder if it can be modified in kable preferably, latex "hack" suggestion is also welcome.
Thanks!
I think for this latex 'hack' solution is much cleaner. In kable also this can be done but that would require changing the data frame (convert column names to row) so that collapse_rows can be used. Anyway, here's the latex way out:
The code that you gave in your questions does not give the column name as in the pdf snapshot. So I edited the code first to get that table:
---
output:
pdf_document:
keep_tex: true
header-includes:
- \usepackage{xcolor}
---
```{r, message=FALSE, warning=FALSE, echo=FALSE}
library(kableExtra)
library(tidyr)
library(dplyr)
data(iris)
iris %>%
as_tibble %>%
gather(.,key = variable,value = value,-Species) %>%
group_by(Species,variable) %>%
summarise(value=mean(value)) %>%
ungroup %>%
spread(.,key = variable,value = value) %>%
mutate('Percentage Change\n(Petal length/ Petal width)'=`Petal.Length`/`Petal.Width`*100) %>%
kable(format='latex',align='c',linesep='',booktabs=TRUE,escape=FALSE,
col.names = linebreak(colnames(.),align = 'c')) %>%
add_header_above(.,c(' '=1,'Parts'=4,' '=1),escape = FALSE) %>%
collapse_rows(columns = c(1,6),valign = 'middle')%>%
kable_styling(latex_options = c('striped','HOLD_position','scale_down'))
```
This gives this:
Note two things in above code:
keep_tex: true: this retains the .tex file generated and can be used to edit.
Use of linebreaks to ensure that the entire column name for last column is not in one line.
Now we make small changes in latex output. In code below the commented out line is the original code generated by kable. This is replaced by the new lines just below the commented out line as indicated.
\begin{table}[H]
\centering
\resizebox{\linewidth}{!}{
\begin{tabular}{cccccc}
\toprule
% \multicolumn{1}{c}{ } & \multicolumn{4}{c}{Parts} & \multicolumn{1}{c}{ } \\
\multirow{2}{*}{Species} & \multicolumn{4}{c}{Parts} & \multirow{2}{*}{\makecell[c]{Percentage Change\\(Petal length/ Petal width)}} \\ % replaced line
\cmidrule(l{3pt}r{3pt}){2-5}
% Species & Petal.Length & Petal.Width & Sepal.Length & Sepal.Width & \makecell[c]{Percentage Change\\(Petal length/ Petal width)}\\
& Petal.Length & Petal.Width & Sepal.Length & Sepal.Width &\\ % replaced line
\midrule
\cellcolor{gray!6}{setosa} & \cellcolor{gray!6}{1.462} & \cellcolor{gray!6}{0.246} & \cellcolor{gray!6}{5.006} & \cellcolor{gray!6}{3.428} & \cellcolor{gray!6}{594.3089}\\
\cmidrule{1-6}
versicolor & 4.260 & 1.326 & 5.936 & 2.770 & 321.2670\\
\cmidrule{1-6}
\cellcolor{gray!6}{virginica} & \cellcolor{gray!6}{5.552} & \cellcolor{gray!6}{2.026} & \cellcolor{gray!6}{6.588} & \cellcolor{gray!6}{2.974} & \cellcolor{gray!6}{274.0375}\\
\bottomrule
\end{tabular}}
\end{table}
This gives the following output:

Table in Bookdown/Huskydown with several features (Citation, Caption, URL, PNG Figure, ...)

I would like to include a table in an R markdown document (Bookdown/Huskydown) which should meet the following requirements. Ideally, the table works with several output formats, e.g. LaTex/PDF and HTML.
Requirements:
Table width: fixed
Cell width: fixed
Vertical alignment: cell content aligned to the top
Text formatting: like bold or italics (best would be if md formatting supported, such that code is output agnostic) and allow for line breaks in longer texts
Citations: should be rendered
URLs: as clickable links both in HTML and LaTex/PDF
Figures: include
figures stored locally, either in
a markdown way ![](Rlogo.png) or
a knitr way knitr::include_graphics("Rlogo.png")
figures taken straight from the web
Caption for the table
Captions text formatting: caption should also allow for text formatting
Footnote: include footnotes in the table
Table numeration: tables are should be numerated
Referencing the table: in the document is needed
Notes regarding different approaches
Fixed cell width: in markdown the number of "-"s in table header determine cell width
Linebreaks:
LaTex:\\linebreak
All others: <br/>
Referencing
LaTex: add \label{foo} => \ref{foo} ( \#ref(foo))
Markdown: add Table: (\#tab:md-table) Caption==> \#ref(tab:md-table))
Comments on different approaches
Markdown: easy coding of tables in markdown
Kable & kableExtra: Versatile R markdown coding of the table, but vertical text alignment obscure and figures are not included in PDF
Pander: achieves the most, but no vertical alignment and footnotes
Huxtable: most promising, but figures are not included in PDF
This is less an answer than providing MWEs for the table shown above
```{r}
# create some random text
library(stringi)
some_text <- stri_rand_lipsum(1)
some_text <- substr(some_text, 1, 75)
# create dataframe with some stuff
figpath <- "figure/"
df <- data.frame(
Citation = c("#R-base", "#R-bookdown"),
Textfield = c("**Formatted** string<br/> -- _Everyone_ needs H^2^O", some_text),
URL = c("[R-url](https://www.r-project.org/)", "[bookdown](https://bookdown.org/)"),
fig_local_md = c(
paste0("![](", figpath, "Rlogo.png){ width=10% height=5% }"),
paste0("![](", figpath, "bookdownlogo.png){ height='36px' width='36px' }")
)#,
# not working:
# fig_local_knitr = c("knitr::include_graphics('figure/Rlogo.png')", "knitr::include_graphics('figure/bookdownlogo.png')")
)
# only include if output format is HTML, else pander throws error
if (knitr::is_html_output()) {
df$fig_web <- c("![](https://www.picgifs.com/glitter-gifs/a/arrows/picgifs-arrows-110130.gif)")
output_format <- "html"
}
if (knitr::is_latex_output()) {
output_format <- "latex"
}
```
markdown
Table: markdown table: markdown styling works in HTML (*italics*, **bold**), LaTex styling in PDF (\\textbf{bold})
| Image | Description |
| :--------------------------------------------------------- | :----------------------------------------------------------- |
| ![](figure/Rlogo.png){ width=10% height=5% } | **Image description** [#R-base] <br/>Lorem ipsum dolor sit amet, ... [R-url](https://www.r-project.org/) |
| ![](figure/bookdownlogo.png){ height='36px' width='36px' } | **Image description** [#R-bookdown] <br/>Lorem ipsum dolor sit amet, ... [bookdown](https://bookdown.org/) |
kable table
```{r kable-table, echo=FALSE, out.width='90%', fig.align = "center", results='asis'}
library(knitr)
kable(df,
caption = "kable table: markdown styling works in HTML (*italics*, **bold**), LaTex styling in PDF (\\textbf{bold})",
caption.short = "md styling works in HTML (*italics*, **bold**), LaTex styling in PDF (\\textbf{bold})"
)
```
kableExtra table
```{r kableExtra-table, echo=FALSE, out.width='90%', fig.align = "center", results='asis'}
library(kableExtra)
# http://haozhu233.github.io/kableExtra/awesome_table_in_pdf.pdf
kable(
df,
caption = "kableExtra table: markdown styling works in HTML (*italics*, **bold**), LaTex styling in PDF (\\textbf{bold})",
output_format, booktabs = T, # output_format = latex, html (specify above)
# align = "l",
valign = "top"
) %>%
kable_styling(full_width = F,
latex_options = c(#"striped",
"hold_position", # stop table floating
"repeat_header") # for long tables
) %>%
column_spec(1, bold = T, border_right = T, width = "30em") %>%
column_spec(2, width = "50em") %>%
column_spec(3, width = "5em") %>%
column_spec(4, width = "10em") %>%
column_spec(5, width = "10em") %>%
footnote(general = "Here is a general comments of the table. ",
number = c("Footnote 1; ", "Footnote 2; "),
alphabet = c("Footnote A; ", "Footnote B; "),
symbol = c("Footnote Symbol 1; ", "Footnote Symbol 2"),
general_title = "General: ", number_title = "Type I: ",
alphabet_title = "Type II: ", symbol_title = "Type III: ",
footnote_as_chunk = T, title_format = c("italic", "underline")
)
```
pander table
```{r pander-table, echo=FALSE, out.width='90%', fig.align = "center", results='asis'}
library(pander)
# https://cran.r-project.org/web/packages/pander/vignettes/pandoc_table.html
pander(
df,
caption = "pander table: markdown styling works in HTML and PDF (*italics*, **bold**), LaTex styling in PDF (\\textbf{bold})",
# style = "multiline", # simple
split.table = Inf, # default = 80 characters; Inf = turn off table splitting
split.cells = c(15, 50, 5, 5, 5), # default = 30
# split.cells = c("25%", "50%", "5%", "10%", "10%"), # no difference
justify = "left"
)
```
huxtable table
```{r huxtable-table, echo=FALSE, out.width='90%', fig.align = "center", results='asis'}
library(dplyr)
library(huxtable)
# https://hughjonesd.github.io/huxtable/
hux <- as_hux(df) %>%
# huxtable::add_rownames(colname = '') %>%
huxtable::add_colnames() %>%
set_top_border(1, everywhere, 1) %>%
set_bottom_border(1, everywhere, 1) %>%
set_bottom_border(final(), everywhere, 1) %>%
set_bold(1, everywhere, TRUE) %>% # bold headlines
set_italic(-1, 1, TRUE) %>% # italics in first column (except the first row)
set_valign("top") %>%
set_width(1) %>%
set_col_width(c(0.10,0.45,0.05,0.10,0.10)) %>%
set_wrap(TRUE) %>%
set_position('left') %>% # fix table alignment (default is center)
add_footnote("Sample Footnote") %>%
set_font_size(4)
table_caption <- 'huxtable table: markdown styling works in HTML (*italics*, **bold**), LaTex styling in PDF (\\textbf{bold})'
# Print table conditional on output type
if (knitr::is_html_output()) {
caption(hux) <- paste0('(#tab:huxtable-table-explicit) ', table_caption)
print_html(hux) # output table html friendly (requires in chunk options "results='asis'")
}
if (knitr::is_latex_output()) {
caption(hux) <- paste0('(\\#tab:huxtable-table-explicit) ', table_caption)
hux # if using chunk option "results='asis'" simply output the table with "hux", i.e. do not use print_latex(hux)
}
```
Referencing the tables
works differently for different table types
Adding a short caption for the LoT
Finally adding a short caption for the table of figures is not really working as desired
(ref:huxtable-table-caption) huxtable-table caption
(ref:huxtable-table-scaption) huxtable-table short caption
```{r huxtable-table, echo=FALSE, out.width='90%', fig.align = "center", fig.cap='(ref:huxtable-table-caption)', fig.scap='(ref:huxtable-table-scaption)', results='asis'}
...
```

How can I split a table so that it appears side by side in R markdown?

I'm writing a document with R markdown and I'd like to put a table. The problem is that this table only has two columns and takes a full page, which is not very beautiful. So my question is : is there a way to split this table in two and to place the two "sub-tables" side by side with only one caption ?
I use the kable command and I tried this solution (How to split kable over multiple columns?) but I could not do the cbind() command.
Here's my code to create the table :
---
title:
author:
date: "`r format(Sys.time(), '%d %B, %Y')`"
output: pdf_document
indent: true
header-includes:
- \usepackage{indentfirst}
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, echo = FALSE}
kable(aerop2, format = "markdown")
```
where aerop2 is my data frame with a list of country names in column 1 and the number of airports in each of these countries in column 2.
I have a long two-column table which is a waste of space. I would like to split this table in two sub-tables and put these sub-tables side by side with a caption that includes both of them.
This doesn't give a lot of flexibility in spacing, but here's one way to do it. I'm using the mtcars dataset as an example because I don't have aerop2.
---
output: pdf_document
indent: true
header-includes:
- \usepackage{indentfirst}
- \usepackage{booktabs}
---
```{r setup, include=FALSE}
library(knitr)
opts_chunk$set(echo = TRUE)
```
The data are in Table \ref{tab:tables}, which will float to the top of the page.
```{r echo = FALSE}
rows <- seq_len(nrow(mtcars) %/% 2)
kable(list(mtcars[rows,1:2],
matrix(numeric(), nrow=0, ncol=1),
mtcars[-rows, 1:2]),
caption = "This is the caption.",
label = "tables", format = "latex", booktabs = TRUE)
```
This gives:
Note that without that zero-row matrix, the two parts are closer together. To increase the spacing more, put extra copies of the zero-row matrix into
the list.
The solution offered by 'user2554330' was very useful.
As I needed to split in more columns and eventually more sections, I further developed the idea.
I also needed to have the tables after the text, not floating to the top. I found a way using kableExtra::kable_styling(latex_options = "hold_position").
I am writing here to share the development and to ask minor questions.
1 - Why did you add the line - \usepackage{indentfirst}?
2 - What is the effect of label = "tables" as kable() input?
(The questions are related to Latex. I probably know to little to understand the explanation in kable() documentation: "label - The table reference label"!)
---
title: "Test-split.print"
header-includes:
- \usepackage{booktabs}
output:
pdf_document: default
html_document:
df_print: paged
---
```{r setup, include=FALSE}
suppressPackageStartupMessages(library(tidyverse))
library(knitr)
library(kableExtra)
split.print <- function(x, cols = 2, sects = 1, spaces = 1, caption = "", label = ""){
if (cols < 1) stop("cols must be GT 1!")
if (sects < 1) stop("sects must be GT 1!")
rims <- nrow(x) %% sects
nris <- (rep(nrow(x) %/% sects, sects) + c(rep(1, rims), rep(0, sects-rims))) %>%
cumsum() %>%
c(0, .)
for(s in 1:sects){
xs <- x[(nris[s]+1):nris[s+1], ]
rimc <- nrow(xs) %% cols
nric <- (rep(nrow(xs) %/% cols, cols) + c(rep(1, rimc), rep(0, cols-rimc))) %>%
cumsum() %>%
c(0, .)
lst <- NULL
spc <- NULL
for(sp in 1:spaces) spc <- c(spc, list(matrix(numeric(), nrow=0, ncol=1)))
for(c in 1:cols){
lst <- c(lst, list(xs[(nric[c]+1):nric[c+1], ]))
if (cols > 1 & c < cols) lst <- c(lst, spc)
}
kable(lst,
caption = ifelse(sects == 1, caption, paste0(caption, " (", s, "/", sects, ")")),
label = "tables", format = "latex", booktabs = TRUE) %>%
kable_styling(latex_options = "hold_position") %>%
print()
}
}
```
```{r, results='asis'}
airquality %>%
select(1:3) %>%
split.print(cols = 3, sects = 2, caption = "multi page table")
```

How to exclude standard errors from stargazer table?

Amazing R gurus,
I am just wondering if there is any way to exclude standard errors from stargazer table.
Here is a quick reproducible example:
---
title: "Test regression"
output: html_document
date: "`r format(Sys.time(), '%d %B, %Y')`"
---
```{r setup, echo=FALSE, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
knitr::opts_chunk$set(warning = FALSE)
knitr::opts_chunk$set(cashe = TRUE)
rm(list=ls())
library(stargazer)
library(ggplot2)
```
```{r, results='asis', echo=FALSE}
fit <- lm(price ~ carat + table + x + y + z, data = diamonds)
stargazer(fit, title="Diamonds Regression",
single.row = TRUE, type ="html", header = FALSE, df=FALSE, digits=2, se = NULL)
```
I would like to see results without standard error like shown in the following screenhsot.
Your time and help is much appreciated.
I just wanted to achieve the same thing, and found the report argument in the stargazer documentation, wich can be used to control the elements shown (and the order) in the output table.
If used like this:
fit <- lm(price ~ carat + table + x + y + z, data = diamonds)
stargazer(fit, title="Diamonds Regression",
single.row = TRUE,
type ="html",
report = "vc*",
header = FALSE,
df=FALSE,
digits=2,
se = NULL
)
It produces the desired output without the need to capture the output first (or any other additional code).
Here is a simple way:
```{r, results='asis', echo=FALSE}
fit <- lm(price ~ carat + table + x + y + z, data = diamonds)
mytab <- capture.output(stargazer(fit, title="Diamonds Regression",
single.row = TRUE, type ="html", header = FALSE, df=FALSE,
digits=2,
apply.se = function(x) { 0 }))
cat(paste(gsub("\\(0.00\\)", "", mytab), collapse = "\n"), "\n")
```
We first capture the output of stargazer and suppress automatic printing. In stargazer we set all standard errors to be 0 (makes the following replacement more failsave). Lastly, we print the output and replace these standard errors.

Table of contents on xaringan slides?

I'm wondering whether it is possible to add a slide showing the table of contents into the document created with xaringan package? Thanks.
Update
Following lines will give you an automated Outline.
Unfortunately I do not know how to automatically reload an R script file in RStudio. If someone knows anything, please feel free to comment or answer in following Question.
The code searches for all the level 1 headers and the Outline header. Then it simply adds the headers as a list and overrides the current script. After reloading the file you have an outline.
---
```{r, echo=FALSE}
require("magrittr")
file_name <- rstudioapi::getSourceEditorContext()[["path"]]
doc <- toc <- readLines(file_name)
tocc <- character()
for (i in 1:length(toc)) {
if(substr(toc[i][1], 1, 2) == "# ") {
toc[i] <- gsub("# ", "", toc[i], fixed = TRUE) %>%
gsub("#", "", ., fixed = TRUE)
tocc <- append(tocc, toc[i])
}
}
tocc <- paste("- ", tocc[-1])
row_outline <- which(doc == "# Outline")
row_body <- which(doc == "---")
row_body <- row_body[which(row_body > row_outline)][1]
doc <- c(doc[1:row_outline], "\n", tocc, "\n", doc[(row_body):length(doc)])
writeLines(doc, file_name)
```
# Outline
---
Old Post
Since Sébastien Rochette's comment did not work for me, I created a very dirty solution with R.
I can think of much nicer solutions but this was a very quick solution. I hope I will update my answer in the near future.
---
```{r, echo=FALSE}
require("magrittr")
toc <- readLines("presentation.Rmd")
tocc <- character()
for (i in 1:length(toc)) {
if(substr(toc[i][1], 1, 2) == "# ") {
toc[i] <- gsub("# ", "", toc[i], fixed = TRUE) %>%
gsub("#", "", ., fixed = TRUE) %>%
paste0(" ", .)
tocc <- append(tocc, toc[i])
}
}
text <- paste(tocc[-1], "\n")
yy <- seq(.9, 0, length = length(text))
```
# Outline
```{r, echo = FALSE}
plot(x = rep(0.2, length(text)), y = yy * 1.035,
xlim = c(0, 1), ylim = c(-0.1, 1), xlab = "", ylab = "", axes = FALSE,
col = "#056EA7", type = "p", pch = 16)
text(x = 0.2, y = yy, labels = text, adj = 0, col = "black")
```
---