= list()
recoding $assertions = c("every link weight is either 1 or 0 (implied by absence)",
recoding"cardinality of the source and target sets is the same")
$xmap = c("`verify_named_all_1to1()`",
recoding"`verify_pairs_all_1to1()`")
$baseR = c("`all(weights == 1)`",
recoding"`length(unique(from) == length(unique(to))`")
$graph = c("$w_{ij} \\in \\{0,1\\} \\ \\forall i,j$",
recoding"$|U| = |V|$",
"$Out_i = In_j = 1 \\ \\forall i,j$")
= list()
collapse $assertions = c("link weights are binary",
collapse"there are more source categories than target categories",
"each source category is assigned to only one target category")
$xmap = c("`verify_named_all_values_unique()`",
collapse"`verify_named_matchset()`")
$baseR = c("`all(weights == 1)`",
collapse"`length(unique(from) > length(unique(to))`")
$graph = c("$w_{ij} \\in \\{0,1\\} \\forall i,j$",
collapse"$|U| > |V|$",
"$Out_i = 1 \\ \\forall i \\in U$")
= list()
split $assertions = c("link weights are fractional or absent",
split"there are more target categories than source categories",
"each source category has at least two outgoing links to the target nomenclature")
$xmap = c("`verify_named_all_names_unique()`",
split"`verify_named_matchset()`")
$baseR = c("`all(weights < 1)`",
split"`length(unique(from)) < length(unique(to))`",
"`length(from) > length(unique(from))`")
$graph = c("$w_{ij} \\in [0, 1) \\forall i,j$",
split"$|U| < |V|$",
"$Out_i > 1 \\ \\forall i \\in U$")
I recently put together this markdown table for a vignette in the {xmap}
package using Visual Mode in Rstudio:
+------------------+-------------------------------------------------------------+------------------------------------------------------------------+-------------------------------------------------------------------------------------+
| x | **Recoding** (1-to-1) | **Collapsing** (M-to-1) | **Splitting** (1-to-M) |
+==================+=============================================================+==================================================================+=====================================================================================+
| Assertions | - every link weight is either 1 or 0 (implied by absence) | - link weights are binary | - link weights are fractional or absent |
| | - cardinality of the source and target sets is the same | - there are more source categories than target categories | - there are more target categories than source categories |
| | | - each source category is assigned to only one target category | - each source category has at least two outgoing links to the target nomenclature |
+------------------+-------------------------------------------------------------+------------------------------------------------------------------+-------------------------------------------------------------------------------------+`verify_named_all_1to1()` | `verify_named_all_values_unique()` | `verify_named_all_names_unique()` |
| xmap functions |
| | | | |`verify_pairs_all_1to1()` | `verify_named_matchset` | `verify_named_matchset` |
| |
| | | | |
| | ... | ... | ... |
+------------------+-------------------------------------------------------------+------------------------------------------------------------------+-------------------------------------------------------------------------------------+`all(weights == 1)` | - `all(weights == 1)` | - `all(weights < 1)` |
| base R | - `length(unique(from) == length(unique(to))` | - `length(unique(from) > length(unique(to))` | - `length(unique(from)) < length(unique(to))` |
| | - `length(unique(from)) == length(from)` | - `length(from) > length(unique(from))` |
| conditions | | -
+------------------+-------------------------------------------------------------+------------------------------------------------------------------+-------------------------------------------------------------------------------------+\{0,1\} \ \forall i,j$ | - $w_{ij} \in \{0,1\} \forall i,j$ | - $w_{ij} \in [0, 1) \forall i,j$ |
| Graph Conditions | - $w_{ij} \in
| | - $|U| = |V|$ | - $|U| > |V|$ | - $|U| < |V|$ |
| | - $Out_i = In_j = 1 \ \forall i,j$ | - $Out_i = 1 \ \forall i \in U$ | - $Out_i > 1 \ \forall i \in U$ | +------------------+-------------------------------------------------------------+------------------------------------------------------------------+-------------------------------------------------------------------------------------+
Visual mode generated a grid style pandoc markdown table, which renders into a table just fine except for the fact that it spills over into the navigation column…
Awkward table spillover
x | Recoding (1-to-1) | Collapsing (M-to-1) | Splitting (1-to-M) |
---|---|---|---|
Assertions |
|
|
|
xmap functions |
… |
… |
… |
base R conditions |
|
|
|
Graph Conditions |
|
|
|
Now, in addition to the spillover issue (which I did not figure out how to fix…), markdown tables can quite awkward to edit, and not that straight forward to version control. So, I thought I’d see if I could generate an similar table using one of the many awesome table rendering packages in R.
Usually when I want to make tables I just call knitr::kable()
and hope for the best. Unsuprisingly this did not work. I’m not sure if/how knitr::kable()
can handle mixed cell types (i.e. text, code, math notation, lists), but luckily for me, it turns out the {pander}
package has all the functionality I needed.
With the help of this stackoverflow answer, How to write (bullet) lists in a table using rmarkdown and pandoc, this is what I came up with:
Enter cell contents
First, let’s get put all the cell contents into R as character strings. For readability, I chose to enter each column as its own list and each bullet point as a separate element in a string vector. Notice that I had to escape all the backslashes using \\
.
Pander the table
Next, I collapse all the string vectors and unlist everything into data.frame columns:
= data.frame(recode = recoding |> lapply(function(x) paste0(paste("*", x), collapse = "\\\n")) |> unlist(),
my_table collapse = collapse |> lapply(function(x) paste0(paste("*", x), collapse = "\\\n")) |> unlist(),
split = split |> lapply(function(x) paste0(paste("*",x), collapse = "\\\n")) |> unlist())
Note that function(x)
basically takes a string vector x
and turns it into a single string of bulleted items by:
- attaching bullets to each element using
y = paste("*", x)
- collapsing the elements with line breaks using
paste0(y, collapse = "\\\n")
. I think the\\\
is required because we have to escape twice?
Finally, we pass the table to pander::pander()
to turn it into a markdown table:
|>
my_table ::pander(caption = "Special Cases {#tbl-special}",
panderkeep.line.breaks = TRUE,
style = "grid",
split.table = Inf,
justify = "left",
split.cells = 20)
recode | collapse | split | |
---|---|---|---|
assertions |
|
|
|
xmap |
|
|
|
baseR |
|
|
|
graph |
|
|
|
The various available options are pretty well documented in ?pander::pandoc.table()
and in the Markdown tables section of the package documentation
Citation
@online{huang2023,
author = {Huang, Cynthia},
title = {Generating Bulleted Lists Inside Pandoc Markdown Tables in
{R} with Pander},
date = {2023-05-15},
url = {https://www.cynthiahqy.com/posts/pander-list-tables},
langid = {en}
}