Rmarkdown Table with Cells That Have Two Values

Rmarkdown table with cells that have two values

We could do it like this, and then use knitr::kable to get the markdown:

two_tables_into_one <- as.data.frame(do.call(cbind, lapply(1:ncol(mtcars), function(i) paste0(mtcars[ , i], " (", some_error_term_for_mtcars[ , i], ")"  ) )))
names(two_tables_into_one) <- names(mtcars)
head(two_tables_into_one)
mpg cyl disp hp drat wt qsec vs
1 21 (2.704) 6 (0.44) 160 (26.011) 110 (3.92) 3.9 (0.4276) 2.62 (0.21513) 16.46 (1.145) 0 (0)
2 21 (0.604) 6 (0.44) 160 (5.211) 110 (6.32) 3.9 (0.0276) 2.875 (0.01513) 17.02 (1.345) 0 (0.1)
3 22.8 (3.304) 4 (0.14) 108 (31.511) 93 (20.42) 3.85 (0.1276) 2.32 (0.51513) 18.61 (0.145) 1 (0.1)
4 21.4 (1.004) 6 (0.44) 258 (16.011) 110 (26.02) 3.08 (0.2276) 3.215 (0.11513) 19.44 (1.345) 1 (0.1)
5 18.7 (2.604) 8 (0.34) 360 (4.311) 175 (30.02) 3.15 (0.0276) 3.44 (0.31513) 17.02 (1.745) 0 (0.1)
6 18.1 (2.404) 6 (0.64) 225 (8.011) 105 (27.92) 2.76 (0.1276) 3.46 (0.21513) 20.22 (1.145) 1 (0)
am gear carb
1 1 (0) 4 (0.03) 4 (0.41)
2 1 (0.1) 4 (0.33) 4 (0.21)
3 1 (0) 4 (0.43) 1 (0.71)
4 0 (0) 3 (0.03) 1 (0.31)
5 0 (0.1) 3 (0.23) 2 (0.41)
6 0 (0.1) 3 (0.33) 1 (0.41)

knitr::kable(head(two_tables_into_one))

Sample Image

or for a plus-minus separator:

two_tables_into_one <- as.data.frame(do.call(cbind, lapply(1:ncol(mtcars), function(i) paste0(mtcars[ , i], " ± ", some_error_term_for_mtcars[ , i]  ) )))
names(two_tables_into_one) <- names(mtcars)
head(two_tables_into_one)
mpg cyl disp hp
1 21 ± 2.704 6 ± 0.44 160 ± 26.011 110 ± 3.92
2 21 ± 0.604 6 ± 0.44 160 ± 5.211 110 ± 6.32
3 22.8 ± 3.304 4 ± 0.14 108 ± 31.511 93 ± 20.42
4 21.4 ± 1.004 6 ± 0.44 258 ± 16.011 110 ± 26.02
5 18.7 ± 2.604 8 ± 0.34 360 ± 4.311 175 ± 30.02
6 18.1 ± 2.404 6 ± 0.64 225 ± 8.011 105 ± 27.92
drat wt qsec
1 3.9 ± 0.4276 2.62 ± 0.21513 16.46 ± 1.145
2 3.9 ± 0.0276 2.875 ± 0.01513 17.02 ± 1.345
3 3.85 ± 0.1276 2.32 ± 0.51513 18.61 ± 0.145
4 3.08 ± 0.2276 3.215 ± 0.11513 19.44 ± 1.345
5 3.15 ± 0.0276 3.44 ± 0.31513 17.02 ± 1.745
6 2.76 ± 0.1276 3.46 ± 0.21513 20.22 ± 1.145
vs am gear carb
1 0 ± 0 1 ± 0 4 ± 0.03 4 ± 0.41
2 0 ± 0.1 1 ± 0.1 4 ± 0.33 4 ± 0.21
3 1 ± 0.1 1 ± 0 4 ± 0.43 1 ± 0.71
4 1 ± 0.1 0 ± 0 3 ± 0.03 1 ± 0.31
5 0 ± 0.1 0 ± 0.1 3 ± 0.23 2 ± 0.41
6 1 ± 0 0 ± 0.1 3 ± 0.33 1 ± 0.41

knitr::kable(head(two_tables_into_one))

Sample Image

But this as.data.frame(do.call(cbind, lapply... seems a bit awkward. Is there a neater way?

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

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:

screenshot

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.

Align multiple tables side by side

Just put two data frames in a list, e.g.

t1 <- head(mtcars)[1:3]
t2 <- head(mtcars)[4:6]
knitr::kable(list(t1, t2))

Note this requires knitr >= 1.13.

Align two data.frames next to each other with knitr?

The development version of knitr (on Github; follow installation instructions there) has a kable() function, which can return the tables as character vectors. You can collect two tables and arrange them in the two cells of a parent table. Here is a simple example:

```{r two-tables, results='asis'}
library(knitr)
t1 = kable(mtcars, format='html', output = FALSE)
t2 = kable(iris, format='html', output = FALSE)
cat(c('<table><tr valign="top"><td>', t1, '</td><td>', t2, '</td><tr></table>'),
sep = '')
```

You can also use CSS tricks like style="float: [left|right]" to float the tables to the left/right.

If you want to set cell padding and spacing, you can use the table attributes cellpadding / cellspacing as usual, e.g.

```{r two-tables, results='asis'}
library(knitr)
t1 = kable(mtcars, format='html', table.attr='cellpadding="3"', output = FALSE)
t2 = kable(iris, format='html', table.attr='cellpadding="3"', output = FALSE)
cat(c('<table><tr valign="top"><td>', t1, '</td>', '<td>', t2, '</td></tr></table>'),
sep = '')
```

See the RPubs post for the above code in action.

Conditionally format each cell containing the max value of a row in a data frame - R Markdown PDF

Using dplyr::mutate(across... and max(c_across... is one way:

---
output:
pdf_document:
toc: yes
---

```{r, include=FALSE}

require("pacman")
p_load(dplyr, forcats, knitr, kableExtra, tinytex, janitor)

segment<- c('seg1', 'seg1', 'seg2', 'seg2', 'seg3', 'seg3')
subSegment<- c('subseg1', 'subseg2', 'subseg1', 'subseg2', 'subseg1', 'subseg2')
var.1<- c(100, 20, 30, 50, 40, 40)
var.2<- c(200, 30, 30, 70, 30, 140)
var.3<- c(50, 50, 40, 20, 30, 40)
var.4<- c(60, 50, 35, 53, 42, 20)

df <-
data.frame(segment, subSegment, var.1, var.2, var.3, var.4) %>%
adorn_totals('row') %>%
rowwise() %>%
mutate(across(var.1:var.4, ~cell_spec(.x, 'latex', bold = ifelse(.x == max(c_across(var.1:var.4)), TRUE, FALSE))))

```

```{r, results='asis'}

df %>%
kable(booktabs = TRUE,
caption = "Title",
align = "c",
escape = FALSE) %>%
kable_styling(latex_options = c("HOLD_position", "repeat_header", "scale_down"),
font_size = 6) %>%
pack_rows(index = table(fct_inorder(df$segment)),
italic = FALSE,
bold = FALSE,
underline = TRUE,
latex_gap_space = "1em",
background = "#f2f2f2")%>%
column_spec(1, monospace = TRUE, color = "white") %>%
row_spec(nrow(df), bold = TRUE)

```

Which results in this pdf output:

Sample Image

KableExtra conditional tables in R

One way of coloring the columns is by using data_color from {gt} package.
You can specify the colors in various ways, including manually supplying the names of your desired colors available in grDevices::colors(). You can also specify the domain with the range of the values in the targeted column.

For example:

library(tidyverse)
library(gt)

iris[45:55,c(1,5)] %>% gt() %>%
data_color(columns = Sepal.Length, colors = scales::col_numeric(
palette = c("tomato","yellow", "green4"),
domain = range(Sepal.Length)))

which results in the following colors

Sample Image

Bold formatting for significant values in a Rmarkdown table

We could do it like this, using pander:

library(pander)
library(Hmisc)

# compute matrix correlation
df3 <- rcorr(as.matrix(mtcars), type="pearson")

# we get a list of three items, first item is df of r values
# third item in df of p values
df3

# make cells of r values bold if p value is <0.01
emphasize.strong.cells(which(df3[[3]] < 0.001, arr.ind = TRUE))
pander(df3[[1]])

Which gives:

----------------------------------------------------------
  mpg cyl disp hp
---------- ----------- ----------- ----------- -----------
**mpg** 1 **-0.8522** **-0.8476** **-0.7762**

**cyl** **-0.8522** 1 **0.902** **0.8324**

**disp** **-0.8476** **0.902** 1 **0.7909**

**hp** **-0.7762** **0.8324** **0.7909** 1

**drat** **0.6812** **-0.6999** **-0.7102** -0.4488

**wt** **-0.8677** **0.7825** **0.888** **0.6587**

**qsec** 0.4187 **-0.5912** -0.4337 **-0.7082**

**vs** **0.664** **-0.8108** **-0.7104** **-0.7231**

**am** **0.5998** -0.5226 **-0.5912** -0.2432

**gear** 0.4803 -0.4927 **-0.5556** -0.1257

**carb** -0.5509 0.527 0.395 **0.7498**
----------------------------------------------------------
[output snipped]

And when rendered into HTML looks like (side-effect of making the row names bold also):

Sample Image

Is something like this possible using only knitr?



Related Topics



Leave a reply



Submit