Search code examples
rlatexknitrbookdownkableextra

Linked text in LaTeX table with knitr/kable


I have the following dataframe:

site_name           | site_url
--------------------| ------------------------------------
3D Printing         | https://3dprinting.stackexchange.com
Academia            | https://academia.stackexchange.com
Amateur Radio       | https://ham.stackexchange.com

I want to generate a third column with the link integrated with the text. In HTML I came up with the following pseudo code:

df$url_name <- "[content of site_name](content of site_url)"

resulting in the following working program code:

if (knitr::is_html_output()) {
    df <- df %>% dplyr::mutate(url_name = paste0("[", df[[1]], "](", df[[2]], ")"))
    knitr::kable(df)
}

Is there a way to this in LaTeX with knitr as well?

(I am preferring a solution compatible with kableExtra, but if this is not possible I am ready to learn whatever table package can do this.)

*** ADDED: I just noticed that the above code works within a normal .Rmd document with the yaml header output: pdf_document. But not in my bookdown project.


Solution

  • The problem is with knitr::kable. It doesn't recognize that the bookdown project needs Markdown output, so you need to tell it that explicitly:

    df <- df %>% dplyr::mutate(url_name = paste0("[", df[[1]], "](", df[[2]], ")"))
    knitr::kable(df, format = "markdown")
    

    This will work for any kind of Markdown output: html_document, pdf_document, bookdown::pdf_book, etc.

    Alternatively, if you need LaTeX output for some other part of the table, you could write the LaTeX equivalent. This won't work for HTML output, of course, but should be okay for the PDF targets:

    df <- df %>% dplyr::mutate(urlName = paste0("\\href{", df[[2]], "}{", df[[1]], "}"))
    knitr::kable(df, format = "latex", escape = FALSE)
    

    For this one I had to change the column name; underscores are special in LaTeX. You could probably get away without doing that if you left it as format = "markdown", but then you'd probably be better off using the first solution.