Search code examples
latexr-markdownkableextraflextable

how to use rmarkdown to display a confusion matrix


My minimal demo rmarkdown example (test.rmd) is given as follows:

---
output: 
  pdf_document: 
    latex_engine: xelatex
    keep_tex: no
colorlinks: yes
header-includes:
- \usepackage[bookmarksopen]{hyperref}
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{multirow}
- \usepackage{tabu}
- \usepackage{float}
- \usepackage{xcolor}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  message = FALSE, 
  warning = FALSE
)
library(flextable)
library(knitr)
library(kableExtra)
```


# code for data

```{r}
library(ISLR) #for Default data
library(MASS) #for LDA function
fit = lda(default~balance+student, data=Default)
tab = table(predict(fit)$class, Default$default); tab #confusion matrix 
Total = sum; atab = addmargins(tab, FUN=Total); atab #change Sum to Total
```

# table: pure latex 


```tex
\documentclass{article}
\usepackage{multirow}
\usepackage{float}

\begin{document}

\begin{table}[!h]
\caption{table via pure latex}\label{mycap}
\centering
\begin{tabular}{ccccc}
\hline
& & \multicolumn{3}{c}{True default status} \\
\cline{3-5}
& & No & Yes & Total \\
\hline
\multirow{3}{*}{Predicted default status}
&  No     &9644 &252 &9896  \\
&  Yes    &23   &23  &104   \\
&  Total  &9667 &333 &10000 \\
\hline
\end{tabular}
\end{table}

\end{document}
```


```{=latex}
\begin{table}[!h]
\caption{table via pure latex}\label{mycap}
\centering
\begin{tabular}{ccccc}
\hline
& & \multicolumn{3}{c}{True default status} \\
\cline{3-5}
& & No & Yes & Total \\
\hline
\multirow{3}{*}{Predicted default status}
&  No     &9644 &252 &9896  \\
&  Yes    &23   &23  &104   \\
&  Total  &9667 &333 &10000 \\
\hline
\end{tabular}
\end{table}
```

# table: rmarkdown

## flextable

```{r error=TRUE}
flextable(atab)
dtab = as.data.frame(atab); ft = flextable(dtab)
ft <- set_caption(ft, "table via flextable"); ft
```

## kableExtra

```{r}
kbl(atab, booktabs = F, caption = "table via kableExtra") |>
add_header_above(c(" ", "True default status" = 3)) |>
kable_styling(latex_options = c("repeat_header")) |>
kable_styling(latex_options = c("hold_position"))
```

As the demo shown, I want to display the confusion matrix result as something similar as the pure latex display. There are several R packages that can combine rmarkdown to display the tables, such as knitr::kable, flexable, etc. ; See https://hughjonesd.github.io/huxtable/design-principles.html for more discussion and comparison. Since I am a little bit familiar with flexable and kableExtra, then I try my best to conduct these two packages.

As the PDF generated from test.rmd shown, I am not satisfied with flexable (maybe I missing something steps). The kableExtra can supply a much better display, but it don't solve the multirow issue (I also the collapse_rows from https://cran.r-project.org/web/packages/kableExtra/vignettes/awesome_table_in_pdf.pdf). How can I solve my problem elegantly and effectively?


Solution

  • Maybe proc_freq() can help.

    data.frame(p = predict(fit)$class, o = Default$default) |> 
      proc_freq(row = "o", col = "p")
    

    enter image description here

    If you need to customize the result, this is possible with usual flextable functions. Note we are working on a new version that will look like the following.

    enter image description here