HTML with Multicolumn Table in Markdown Using Knitr

HTML with multicolumn table in Markdown using knitr

Ok, so I wrote it myself...

The package is as of version 1.0 called htmlTable and is available both from CRAN and and my blog, gforge.se/packages. I hope you find it useful. I've created a few vignettes to help with all the options.

Have two columns in Markdown

You can't, at least not with pure Markdown as it doesn't have any concept of columns. As explained in the rules:

The idea for Markdown is to make it easy to read, write, and edit prose. HTML is a publishing format; Markdown is a writing format. Thus, Markdown’s formatting syntax only addresses issues that can be conveyed in plain text.

For any markup that is not covered by Markdown’s syntax, you simply use HTML itself.

In fact, the best way would be to have each code block wrapped in a <div> with the appropriate class assigned to each div. However, most Markdown parsers do not parse Markdown inside a raw HTML block. Therefore, you may need to also define the code block in raw HTML as well. Check your parser's list of features to find out. In the event you are not able to define your own CSS to use separately from the Markdown (to style the HTML), you will also need to define the styles inline in the HTML. This question includes a nice sample of what that might look like. Just replace the comments with the appropriate code blocks. If you have to define your code blocks in raw HTML, they would look like this:

<pre><code class="language-c">int foo (void) 
{
int i;
}
</code></pre>

So, the final document that is sure to work in all (most?) Markdown parsers would look like this:

# Rule 1
Description for rule 1.

<div style="-webkit-column-count: 2; -moz-column-count: 2; column-count: 2; -webkit-column-rule: 1px dotted #e0e0e0; -moz-column-rule: 1px dotted #e0e0e0; column-rule: 1px dotted #e0e0e0;">
<div style="display: inline-block;">
<h2>Good</h2>
<pre><code class="language-c">int foo (void)
{
int i;
}
</code></pre>
</div>
<div style="display: inline-block;">
<h2>Bad</h2>
<pre><code class="language-c">int foo (void) {
int i;
}
</code></pre>
</div>
</div>

Note that that uses one of many different ways of defining columns in CSS. Different methods may or may not work in different browsers. YMMV.

Create a LaTeX style table in Markdown with colors

The problem is that rmarkdown automatically loads the xcolor package way before it inserts the header-includes, so you don't have a chance to influence the package options there.

As a workaround, you can define table as class option, which will then be passed to all packages, including the xcolor package (and hope for the best that it won't cause any problems in other packages...)

---
title: "misc"
author: "Me"
date: "`r Sys.Date()`"
output:
pdf_document:
keep_tex: true
extra_dependencies: caption
number_sections: yes
fig_caption: yes
classoption: table
header-includes:
- \usepackage{float}
- \usepackage{framed}
- \usepackage{fontawesome}
- \usepackage{caption}
- \usepackage{multirow}
fontsize: 11pt
urlcolor: blue
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

```{=latex}

\begin{table}[htbp]
\begin{tabular}{|
>{\columncolor[HTML]{656565}}c |lcccc|}
\hline
\cellcolor[HTML]{656565}{\color[HTML]{FFFFFF} } & \multicolumn{5}{c|}{\cellcolor[HTML]{656565}{\color[HTML]{FFFFFF} Type of Distribution}} \\ \cline{2-6}
\cellcolor[HTML]{656565}{\color[HTML]{FFFFFF} } & \multicolumn{1}{l|}{} & \multicolumn{1}{l|}{Lognormal} & \multicolumn{1}{l|}{Exponential} & \multicolumn{1}{l|}{Gamma} & \multicolumn{1}{l|}{Weibull} \\ \cline{2-6}
\cellcolor[HTML]{656565}{\color[HTML]{FFFFFF} } & \multicolumn{1}{l|}{Box-Cox} & \multicolumn{1}{c|}{Y} & \multicolumn{1}{c|}{Y} & \multicolumn{1}{c|}{\cellcolor[HTML]{9B9B9B}\textbf{Y}} & \cellcolor[HTML]{9B9B9B}\textbf{Y} \\ \cline{2-6}
\cellcolor[HTML]{656565}{\color[HTML]{FFFFFF} } & \multicolumn{1}{l|}{Exponential} & \multicolumn{1}{c|}{Y} & \multicolumn{1}{c|}{Y} & \multicolumn{1}{c|}{Y} & Y \\ \cline{2-6}
\cellcolor[HTML]{656565}{\color[HTML]{FFFFFF} } & \multicolumn{1}{l|}{Simple power} & \multicolumn{1}{c|}{Y} & \multicolumn{1}{c|}{\cellcolor[HTML]{9B9B9B}\textbf{Y}} & \multicolumn{1}{c|}{\cellcolor[HTML]{9B9B9B}\textbf{Y}} & \cellcolor[HTML]{9B9B9B}\textbf{Y} \\ \cline{2-6}
\multirow{-6}{*}{\cellcolor[HTML]{656565}{\color[HTML]{FFFFFF} \begin{tabular}[c]{@{}c@{}}Type of\\ transformation\end{tabular}}} & \multicolumn{1}{l|}{Logarithmic} & \multicolumn{1}{c|}{\cellcolor[HTML]{9B9B9B}\textbf{Y}} & \multicolumn{1}{c|}{Y} & \multicolumn{1}{c|}{\cellcolor[HTML]{9B9B9B}\textbf{N}} & \cellcolor[HTML]{9B9B9B}\textbf{N} \\ \hline
\end{tabular}
\end{table}
```

How to split kable over multiple columns?

kable is a great tool, but has limits. For the type of table you're describing I would use one of two different tools depending on output wanted.

  • Hmisc::latex for .Rnw -> .tex -> .pdf

  • htmlTable::htmlTable for .Rmd -> .md -> .html

Here is an example of the latter:

dd <- data.frame(state=state.name, freq=1:50)
dd2 <- cbind(dd[1:25, ], dd[26:50, ])

library(htmlTable)
htmlTable(dd2,
cgroup = c("Set 1:25", "Set 26:50"),
n.cgroup = c(2, 2),
rnames = FALSE)

Sample Image

knitr printing list of data.frames with each table on new page

You can use purrr::imap to get the index in the .y variable:

``` r
library(kableExtra)
library(tidyverse)
library(purrr)

mt1 <-
matrix(
data = runif(n = 200, min = 101, max = 999)
,
nrow = 20
,
ncol = 10
,
byrow = TRUE
,
dimnames = list(LETTERS[1:20], paste0("V", 1:10))
)

df1 <- data.frame(Name = row.names(mt1), mt1)

dfs <-
unname(split.default(df1[,-1], as.integer(gl(
ncol(df1) - 1, 5, ncol(df1) - 1
))))

f <- function() {
for (i in 1:length(dfs)) {
print(
kable(
cbind(df1[1], dfs[i])
,
format = 'latex'
,
row.names = FALSE
) %>%
row_spec(
row = c(0),
bold = TRUE,
italic = TRUE,
align = "l"
)
)
if (i < length(dfs)) {
cat("\n\n\\newpage\n")
}
}
}

f_map <- function() {
invisible(dfs %>% purrr::imap(~ {
print(
kable(cbind(df1[1], .x)
, format = 'latex'
, row.names = FALSE) %>%
row_spec(
row = c(0),
bold = TRUE,
italic = TRUE,
align = "l"
)
#cat("\n\n\\newpage\n")
)
if (.y < length(dfs))
cat("\n\n\\newpage\n")
}))
}

identical(capture.output(f()), capture.output(f_map()))
#> [1] TRUE

microbenchmark::microbenchmark( f = {res <- capture.output(f())}, f_map = {res <- capture.output(f_map())})
#> Unit: milliseconds
#> expr min lq mean median uq max neval cld
#> f 7.908510 8.431997 9.662659 9.012099 10.10318 15.42358 100 a
#> f_map 7.983586 8.462561 9.797256 9.150356 10.71692 16.20676 100 a
```

<sup>Created on 2020-07-23 by the [reprex package](https://reprex.tidyverse.org) (v0.3.0)</sup>

As stated by @CL, this is not faster nor shorter than a simple loop.

How make 2 column layout in R markdown when rendering pdf?

New pandoc version have made this easier since my original answer. According to pandoc's manual, you can now specify classoptions directly in the YAML front matter:

---
classoption:
- twocolumn
---

The new div notation also allows for inserting two column sections anywhere in the document, working for most formats

:::::::::::::: {.columns}
::: {.column width="40%"}

contents...

:::
::: {.column width="60%"}

contents...

:::
::::::::::::::

Original answer

You can use the article option twocolumn to format the whole document in two columns. Add this to your yaml front matter:

---
output:
pdf_document:
pandoc_args: [
"-V", "classoption=twocolumn"
]
---


Related Topics



Leave a reply



Submit