I'm looking for tidy way to add a hyperlink incorporating a fontawesome icon to an Rmarkdown table (kable) — for incorporation in an html bookdown page.
In other parts of my document, I've used the icon package, to render a hyperlinked fontawesome icon (outside of a table) using standard markdown syntax, e.g.:
`r icon::fa("file-pdf", size = 5)](https://www.google.com/){target="_blank"}`
But this approach doesn't work when I've attempted to incorporate it as part of a kable.
```{r}
library(icon)
library(knitr)
library(tidyverse)
## note this code throws the following error: Error in
## as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors =
## stringsAsFactors) : cannot coerce class "c("knit_asis",
## "knit_icon")" to a data.frame
link_location <- "www.google.com"
data_test_1 <- data.frame(
file = c('Version 1', 'Version 2', 'Version 3'),
last_updated = Sys.Date(),
pdf_logo = icon::fa("file-pdf")) %>%
mutate(pdf_logo = cell_spec(pdf_logo,
link = link_location)) %>%
kable("html", escape = F, align = "c")
data_test_1
```
So far I've come up with a workaround that involves downloading the .svg file from the fontawesome website and adding it as an image. It works... sort of, but I would prefer to have the ability to change the size of the icon and make it more easily reproducible.
This is the code for my current workaround.
```{r fontawesome_table ='asis'}
library(tidyverse)
library(kableExtra)
## download svg from location manually
https://fontawesome.com/icons/r-project?style=brands
data_test_2 <- data.frame(
file = c('Version 1', 'Version 2', 'Version 3'),
last_updated = Sys.Date(),
R_logo = "![](r-project-brands.svg)") %>%
mutate(R_logo = cell_spec(R_logo, link = "https://cran.r-
project.org/")) %>%
kable("html", escape = F, align = "c")
data_test_2
```
Which produces this output...
Does anyone have any ideas for how I could either, adjust the size the icon in the table, or call the icon from another package/css to create a more tidy solution?
Here is a way using the fontawesome package instead. I also had to use a custom link building function:
```{r, echo = F, message=F, warning=F}
library(fontawesome)
library(knitr)
library(tidyverse)
library(kableExtra)
## note this code throws the following error: Error in
## as.data.frame.default(x[[i]], optional = TRUE, stringsAsFactors =
## stringsAsFactors) : cannot coerce class "c("knit_asis",
## "knit_icon")" to a data.frame
link_location <- "www.google.com"
addLink <- function() {
paste0("", as.character(fa("file-pdf")), "")
}
data_test_1 <- data.frame(file = c('Version 1', 'Version 2', 'Version 3'),
last_updated = Sys.Date(),
pdf_logo = addLink())
kable(data_test_1, escape = F, align = "c")
```
Another solution is the icons package. With icons you cannot only use fontawesome but several icon packages incl. Material icons, e.g.
Install it with devtools::install_github("mitchelloharawild/icons").
Download the font you want to use, here: download_fontawesome().
Now access the icon with either fontawesome("rocket", style = "solid") or icons::fontawesome$solid$rocket.
In an Rmarkdown document like this:
```{r icon-chunk}
fontawesome("rocket", style = "solid")
```
or inline like this
`r icons::fontawesome("rocket", style = "solid")`
In some cases you may need backticks. E.g. for the R icon
fontawesome$brands$`r-project`
Related
I am using the Xaringan Theme for my RStudio Markdown presentations.
All works fine but I want to change the bibliography style from "authoryear" to the Chicago Manual of Style Author-Date Version.
Does anyone know how to do that?
Here is the code so far:
```{r, load_refs, include=FALSE, cache=FALSE}
library(RefManageR)
BibOptions(check.entries = FALSE,
bib.style = "authoryear",
cite.style = "authoryear",
style = "markdown",
hyperlink = FALSE,
dashed = FALSE)
lit <- ReadBib("pwaLiterature.bib", check = FALSE)
```
I am trying to add a subscript to a caption generated in officer.
I am creating the caption like this:
library(officer)
doc <- read_docx('empty_file.docx')
autonum <- run_autonum(seq_id = 'fig', pre_label = 'Figure ')
caption <- block_caption(label='My caption includes SO2.', style = "caption", autonum = autonum)
doc <- body_add_caption(doc, caption)
print(doc, target = 'output.docx'))
However, now I'd like to put the '2' in 'SO2' in subscript. I know how to generate subscripts:
fp_text_prop <- fp_text(color='orange')
prop_mod <- update(fp_text_prop, vertical.align = 'subscript')
paragraph <- fpar(ftext('SO', prop = fp_text_prop), ftext('2', prop = prop_mod)))
But I can't use the resulting fpar inside a caption, as body_add_caption expects the output from block_caption and block_caption expects a normal string as argument for the label=.
How can I put an fpar, or alternatively, a subscript inside a caption?
I have found a solution that is a bit involved but seems to work.
library(officer)
doc <- read_docx('empty_file.docx')
autonum <- run_autonum(seq_id = 'fig', pre_label = 'Figure ')
fp_text_prop <- fp_text(color='orange')
prop_mod <- update(fp_text_prop, vertical.align = 'subscript')
caption <- fpar(autonum, ftext('SO', prop = fp_text_prop), ftext('2', prop = prop_mod)))
doc <- body_add_fpar(x=doc, value=caption, style = 'caption')
print(doc, target = 'output.docx'))
There are a couple of caveats: fp_text_prop should match the normal style of the captions and style = 'caption' should be changed to pick the correct style for captions in your document.
This has plagued me for too long, I would appreciate help. I have been investing time into kable, but it hasn't quite worked out for me the way I would like. I am looking to create multi grouped rows as in the image
The code to do this is as follows:
collapse_rows_dt <- expand.grid( District = sprintf('District %s', c('1', '2')), City = sprintf('City %s', c('1', '2')), State = sprintf('State %s', c('a', 'b')), Country = sprintf('Country with a long name %s', c('A', 'B'))
)
collapse_rows_dt <- collapse_rows_dt[c("Country", "State", "City", "District")]
collapse_rows_dt$C1 = rnorm(nrow(collapse_rows_dt))
collapse_rows_dt$C2 = rnorm(nrow(collapse_rows_dt))
kbl(collapse_rows_dt, booktabs = T, align = "c", linesep = '') %>%
collapse_rows(1:3, row_group_label_position = 'stack')
The problem is that when I run this in R markdown I get the HTML version in the output (see below)
This obviously is not good enough. I CAN get the correct output (first image) if I knit to pdf, but that's it. If I try doing save_kable() it turns out in the HTML format as in the second image. Kniting to pdf every time is so impractical that I can't possible use kable anymore if I can't fix this. That is a big deal for me.
If I set format='latex' then nothing shows up inline and when I try to kable_save() I get this error message:
this is Xtex version 3....(tex live 2020/w32Tex) preloaded format=xlatex) restricted \write18 enabled.
Entering extended mode
Followed by a pop that informs me (R crashes)
R session aborted, r encoutered a fatal error
All HTML tables that don't require latex show up inline appropriately and will save as their actual image.
Relevant Up to Date Packages:
- library(webshot)
library(tinytex) (also tried without)
library(magick)
library(plyr)
library(tidyverse)
library(dplyr)
library(knitr)
library(skimr)
library(kableExtra)
Also:
Ghostscript 9.52 is current and set to environment
Miktext 2.9
Have Tried:
updating imageMagick via install.packages(magick
editing the policy.xls in ImageMagick to bypass a security feature ImageMagick security policy 'PDF' blocking conversion
Manually installing the following Latex packages
library(tinytex)tlmgr_install(pkgs = 'standalone')tlmgr_install(pkgs
= 'preview')tlmgr_install(pkgs = 'polyglossia')tlmgr_install(pkgs = 'xltxtra')tlmgr_install(pkgs = 'realscripts')
Setting Mixtex to environment path
If you want to knit and include the image produced via LaTeX and PDF, you can use kableExtra::as_image
---
output: html_document
---
```{r}
library(kableExtra)
library(magrittr)
collapse_rows_dt <- expand.grid( District = sprintf('District %s', c('1', '2')), City = sprintf('City %s', c('1', '2')), State = sprintf('State %s', c('a', 'b')), Country = sprintf('Country with a long name %s', c('A', 'B'))
)
collapse_rows_dt <- collapse_rows_dt[c("Country", "State", "City", "District")]
collapse_rows_dt$C1 = rnorm(nrow(collapse_rows_dt))
collapse_rows_dt$C2 = rnorm(nrow(collapse_rows_dt))
kbl(collapse_rows_dt, "latex", align="c", linesep="", booktabs = T) %>%
collapse_rows(1:3, row_group_label_position = 'stack') %>%
kable_styling(latex_options = c("striped", "scale_down")) %>%
as_image()
```
I want a table to have bullet points in one column and to have a specific table width (in order to be placed on one page when rendered to PDF).
How can I achieve this in rmarkdown using one of the many packages out there?
What I have tried and have so far:
---
output: pdf_document
---
```{r, include = FALSE}
df <- data.frame(col1 = "Some really long text here. I mean some reeeeeaaly loooong text. So long, it should be wrapped. Really.",
col2 = "* bullet point 1\n * bullet point 2", col3 = "Yes, there is still another column.")
```
# Attempt 1: kableExtra
```{r, echo = FALSE, warning = FALSE}
library(kableExtra)
df1 <- df
df1$col2 <- linebreak(df1$col2)
knitr::kable(df1, escape = FALSE) %>% column_spec(1, width = "15em")
```
# Attempt 2: pander
```{r, echo = FALSE}
pander::pander(df, keep.line.breaks = TRUE, style = 'grid', justify = 'left')
```
This renders to:
As you can see both options have caveats. The kableExtra version does have a specific table width that fits on one page but does not show bullet points nicely. Whereas the pander solution renders the bullet points nicely but spans multiple pages, because I don't know how to specifiy the table width in pander.
Is there a solution that can do both?
Related questions are for example here and there.
An alternative solution based on kableExtra (optional: with footnotes)
This approach allows to add a caption, to manually add footnotes within the table, and to fix column widths.
To create the bullet point list:
"thicker" \cdots from LaTex are employed as bullets (alternatives see here)
linebreaks are forced with \n (indentation is therefore not as nice as with the pander approach from #daroczig).
MWE
library(stringi); library(kableExtra); library(dplyr)
string_short <- "Descriptor"
string_long <- substr(stri_rand_lipsum(1), 1, 50)
# add footnotes manually within table
string_bulletlist <- "$\\boldsymbol{\\cdot}$ bullet point 1: foo$^{a}$ \n $\\boldsymbol{\\cdot}$ bullet point 2: bar$^{b}$"
df <- data.frame(col1 = c(string_short, string_short),
col2 = c(string_bulletlist, string_bulletlist),
col3 = c(string_long, string_long)
)
col_names <- c("Descriptor", "Description with list", "Some comment")
# header: bold column names
colnames(df) <- paste0("\\textbf{", col_names,"}")
# add footnote with kableExtra commands
names(df)[1] <- paste0(names(df)[1], footnote_marker_symbol(1))
df %>%
mutate_all(linebreak) %>% # required for linebreaks to work
kable(
"latex",
escape = F,
booktabs=TRUE,
align = "l",
caption = 'kableTable with bullet list and footnote') %>%
# kable_styling(full_width = F) %>% # makes no difference here
footnote(general = "General comment of the table.",
alphabet = c("Footnote A;", "Footnote B;"),
symbol = c("Footnote Symbol 1")) %>%
column_spec(1, width = "5em") %>% # fix width column 1
column_spec(2, width = "10em") %>% # fix width column 2
column_spec(3, width = "15em") # fix width column 3
To [improve line spacing[(https://stackoverflow.com/questions/53794142/increase-line-row-spacing-with-kableextra), one can add the following before & after code chunk in the Rmd:
\renewcommand{\arraystretch}{1.5} <!-- increase line spacing for the table -->
RMD CHUNK HERE
\renewcommand{\arraystretch}{1} <!-- reset row hight/line spacing -->
Comment:
I also tried the pander approach from #daroczig and made the following experiences:
Pro: nice line spacing plus a "real bullet list" (compared to the $\boldsymbol{\cdot}$-workaround in the kableExtra approach).
Con: a large blank space is included after the bullet list
In addition, when using the pander approach in an Rmd file using the huskydown thesis template the footnotes greatly messed up the table alignment.
Use the split.table parameter of pandoc.table (that is being called by pander in the background) or disable the table splitting in general via panderOptions's table.split.table, eg
pander::pander(df, keep.line.breaks = TRUE, style = 'grid', justify = 'left', split.table = Inf)
or
library(pander)
panderOptions('table.style', 'grid')
panderOptions('table.alignment.default', 'left')
panderOptions('table.split.table', Inf)
panderOptions('keep.line.breaks', TRUE)
pander(df)
I am using knitr::kable() to render tables as part of an R Markdown document (that itself is part of a bookdown project). In particular, the booktabs option (through setting the booktabs argument to equal TRUE) renders the table in a nice-looking way. However, I'd like for there not to be a space after every five rows.
Here, for example, is the code and how the table in the bookdown demo appears when rendered as a PDF:
knitr::kable(
head(iris, 20), caption = 'Here is a nice table!',
booktabs = TRUE
)
I'd like for the space that aappears after every five rows to not be included, but I cannot seem to find a setting in knitr::kable() that does this.
The reason why the row height is not always equal is that by default, kable inserts a \addlinespace every 5 rows when booktabs is specified as TRUE, as is shown here:
linesep = if (booktabs) c('', '', '', '', '\\addlinespace') else '\\hline'
To alter this, add linesep = "" as an argument to kable().
knitr::kable(
head(iris, 20), caption = 'Here is a nice table!',
booktabs = TRUE,
linesep = ""
)
See Get rid of \addlinespace in kable for more details.
It is also worth saying that you can play around with this option if you want to change the style. For example linesep = c("", "", "", "\\hline") would add a horizontal line every four spaces.
Based on the example above I was interested in controlling the separation. That works nicely with the following helper function. This makes it possible to control the locations of the line separation.
linesep<-function(x,y=character()){
if(!length(x))
return(y)
linesep(x[-length(x)], c(rep('',x[length(x)]-1),'\\addlinespace',y))
}
knitr::kable(
head(iris, 20), caption = 'Here is a nice table!',
booktabs = TRUE,
linesep = linesep(c(3,2,1,1,3,5,4,1))
)
Bart's answer failed to work for me on my remote server when using prettyNum() on the table and passing the output to kableExtra::kable_styling(), where it just added an column full of NAs and no linespaces. It seems to work fine on my local machine, so I can't reproduce the error.
Anyway, this alternative solution works for me (but only when passing the table to kableExtra for some reason):
linesep <- function(table, groups) {
sep_indx <- rep("", nrow(table))
sep_indx[cumsum(groups)] <- '\\addlinespace'
return(sep_indx)
}
knitr::kable(
head(iris, 20),
caption = 'Here is a nice table!',
booktabs = TRUE,
linesep = linesep(head(iris, 20), c(3, 2, 1, 1, 3, 5, 4, 1))
) %>% kableExtra::kable_styling(latex_options = c("scale_down", "HOLD_position"))
example