Adding a row spanning column header to a knitr kable table - r

kableExtra can add header rows with items spanning multiple columns in tables produces with kable
library(tidyverse)
library(knitr)
library(kableExtra)
mat <- matrix(1:4,2,dimnames=list(c("a","b"),c("x","y")))
mat %>% kable("html") %>% add_header_above(c(" " = 1,"row header" = 2))
I would like to have a column header also, like this:
Can it be done?

i don't think you can do it but i found a way to fix your issue
mat <- data.frame(a = c("row header","row header"),b = c("a","b"),c = c("x","y"))
mat %>% kable("html") %>% add_header_above(c(" " = 1,"row header" = 2))
kable(mat, align = "c",col.names = c("","","")) %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left",font_size = 12)%>%
column_spec(1, bold = T) %>%
collapse_rows(columns = 1, valign = "middle")%>%
add_header_above(c(" " = 1, "row header" = 2))
i hope this helps you

Building on what you told me I was able to solve my problem completely:
mat <- data.frame(a = c("column header","column header"),b = c("a","b"),c = c("x","y"))
kable(mat, align = "c",col.names = c("","","")) %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left",font_size = 12)%>%
column_spec(1, bold = T,width="3em",extra_css="transform: rotate(-90deg);") %>%
collapse_rows(columns = 1, valign = "middle")%>%
add_header_above(c(" " = 1, "row header" = 2))

Related

How to split row from table if column exceeds the page capacity in R Markdown?

Below I have a script that contains a 5th text column that had so much written it exceeded the size of the page. Though I added longtable = T and latex_options= "repeat_header" it only continues the table through multiple pages but if the row exceeds the page it gets cut off. How can I keep the table moving along while not losing text.
df %>%
kableExtra::kbl(.,booktabs = T,longtable = T)%>%
row_spec(0,background = "#F6F6F6",color="black")%>%
kable_styling(bootstrap_options = "striped", font_size = 9,latex_options =
c("hold_position","repeat_header"),position = "left") %>%
column_spec(1,width = "2.0cm") %>%
column_spec(2,width = "2.5cm") %>%
column_spec(3,width = "2.5cm") %>%
column_spec(4,width = "4.5cm")%>%
column_spec(5,width="10.0cm")
Here's a workaround by splitting the cell with long text. It works by splitting the text into two chunks based on word count so could easily be adjusted by trial and error.
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(kableExtra)
library(wakefield) # for generating long text
library(dplyr)
library(tidyr)
library(stringr)
```
```{r df, include=FALSE}
set.seed(123)
#sample dataset
df <- data.frame(a = 1:6,
b = month.name[1:6],
c = names(mtcars)[1:6],
d = names(islands)[1:6],
e = c(paragraph(2), paste(paragraph(6), collapse = "; "), paragraph(3)))
#create new data frame, cells with long text split into to
df_new <-
df %>%
mutate(f = ifelse(str_length(e)>2000, word(e, 301, -1), NA_character_),
e = ifelse(str_length(e)>2000, word(e, 1, 300), e)) %>%
pivot_longer(cols = c(f, e), values_to = "e") %>%
na.omit() %>%
arrange(a, name) %>%
select(-name)
```
```{r long-table, results='asis'}
df_new %>%
kbl(booktabs = TRUE,
longtable = TRUE) %>%
row_spec(0, background = "#F6F6F6", color = "black") %>%
landscape() %>%
kable_styling(bootstrap_options = "striped",
font_size = 9,
latex_options = c("hold_position","repeat_header"),position = "left") %>%
column_spec(1, width = "2.0cm") %>%
column_spec(2, width = "2.5cm") %>%
column_spec(3, width = "2.5cm") %>%
column_spec(4, width = "4.5cm") %>%
column_spec(5, width = "10.0cm")
```

Avoid repeating the same styling with kable_styling

Using Rmarkdown and kable, I need to repeat several tables with the same formatting but with different datasets.
For example, in the following two chunks, what is changing is the DF, the variable used to sort and the caption.
Is there any way to avoid repeating 90% of the same code for each chunk?
kable(Crib1 %>% arrange(-Z1) %>%
select(Ranking = TYP, SID, Statement, FA1:FA3), longtable = TRUE, booktabs = TRUE, caption = "Crib Sheet - Factor 1") %>%
collapse_rows(1, latex_hline = "major", valign = "top") %>%
kable_styling(full_width = FALSE, latex_options = c("hold_position", "condensed", "repeat_header"), font_size = 9) %>%
column_spec(1, bold=TRUE) %>%
column_spec(3, width = "18em", italic = TRUE) %>%
column_spec(4, bold = TRUE)
kable(Crib2 %>% arrange(-Z2) %>%
select(Ranking = TYP, SID, Statement, FA1:FA3), longtable = TRUE, booktabs = TRUE, caption = "Crib Sheet - Factor 2") %>%
collapse_rows(1, latex_hline = "major", valign = "top") %>%
kable_styling(full_width = FALSE, latex_options = c("hold_position", "condensed", "repeat_header"), font_size = 9) %>%
column_spec(1, bold=TRUE) %>%
column_spec(3, width = "18em", italic = TRUE) %>%
column_spec(4, bold = TRUE)
I am trying to build a function
createKableCrib <- function(factor){
Crib <- rlang::sym(paste("Crib", factor, sep=""))
Z <- rlang::sym(paste("Z", factor, sep=""))
cap <- paste("Crib Sheet - Factor", factor, sep=" ")
kable(!!Crib %>% arrange(!!(-Z)) %>%
select(Ranking = TYP, SID, Statement, FA1:FA3),
longtable = TRUE, booktabs = TRUE, caption = cap) %>%
collapse_rows(1, latex_hline = "major", valign = "top") %>%
kable_styling(full_width = FALSE, latex_options = c("hold_position", "condensed", "repeat_header"), font_size = 9) %>%
column_spec(1, bold=TRUE) %>%
column_spec(3, width = "18em", italic = TRUE) %>%
column_spec(4, bold = TRUE)
}
createKableCrib("1")
But I get the following error:
Error in UseMethod("arrange_") :
no applicable method for 'arrange_' applied to an object of class "name"
Best,
Damien
It looks like you may have gotten there already, but here is an example that seems to work with the use of Curly-Curly instead of the original Bang-Bang (https://www.brodrigues.co/blog/2019-06-20-tidy_eval_saga/).
Didn't have your data, but tried with mtcars and iris. If your columns are the same you could add the select statement after arrange.
library(dplyr)
library(knitr)
library(kableExtra)
create_kable <- function(data, column, title) {
kable({{data}} %>%
arrange({{column}}),
longtable = TRUE, booktabs = TRUE, caption = title) %>%
collapse_rows(1, latex_hline = "major", valign = "top") %>%
kable_styling(full_width = FALSE, latex_options = c("hold_position", "condensed", "repeat_header"), font_size = 9) %>%
column_spec(1, bold=TRUE) %>%
column_spec(3, width = "18em", italic = TRUE) %>%
column_spec(4, bold = TRUE)
}
create_kable(mtcars, mpg, "Crib Sheet - Factor 1")
create_kable(iris, Sepal.Length, "Crib Sheet - Factor 2")
Here is what I found so far.
Not completely satisfactory, as I wanted to be able to create the df name within the function, but I keep on getting errors.
createKableCrib <- function(df, factor){
Z <- paste("Z", factor, sep="")
cap <- paste("Crib Sheet - Factor", factor, sep=" ")
kable(df %>% arrange_at(.vars=desc(Z)) %>%
select(Ranking = TYP, SID, Statement, FA1:FA3),
longtable = TRUE, booktabs = TRUE, caption = cap) %>%
collapse_rows(1, latex_hline = "major", valign = "top") %>%
kable_styling(full_width = FALSE, latex_options = c("hold_position", "condensed", "repeat_header"), font_size = 9) %>%
column_spec(1, bold=TRUE) %>%
column_spec(3, width = "18em", italic = TRUE) %>%
column_spec(4, bold = TRUE)
}
createKableCrib(Crib1, "1")

How can I get rid of the back-tic inside a table generated by `kableExtra` in `xaringan` slides?

How can I get rid of the back-tic inside this table generated by kableExtra in xaringan slides?
library(knitr)
library(kableExtra)
text_tbl <- data.frame(
a= c("1", "2","...","L",""),
b= c("$O_{11}$","$O_{21}$","...","$O_{L1}$","$n_{.1}$"),
c= c("$O_{11}$","$O_{22}$","...","$O_{L2}$","$n_{.2}$"),
d= c("...","...","...","...","..."),
e= c("$O_{C1}$","$O_{C2}$","...","$O_{LC}$","$n_{.C}$"),
f= c("$n_{1.}$","$n_{2.}$","...","$n_{L.}$","$N$"))
kable(text_tbl, "html", booktabs = T, col.names = c("","1","2","...","C"," "), escape=F) %>%
kable_styling(full_width = F,bootstrap_options = "striped") %>%
add_header_above(c(" Variável A", "Variável B" = 4, " ")) %>%
column_spec(1, bold = T) %>%
column_spec(2)
I inspected the HTML code generated, and I didn't see any back-tics.
You can replace the maths $ with \\( or \\). E.g. $O_{11}$ with \\(O_{11}\\) instead.
library(knitr)
library(kableExtra)
text_tbl <- data.frame(
a= c("1", "2","...","L",""),
b= c("\\(O_{11}\\)","\\(O_{21}\\)","...","\\(O_{L1}\\)","\\(n_{.1}\\)"),
c= c("\\(O_{11}\\)","\\(O_{22}\\)","...","\\(O_{L2}\\)","\\(n_{.2}\\)"),
d= c("...","...","...","...","..."),
e= c("\\(O_{C1}\\)","\\(O_{C2}\\)","...","\\(O_{LC}\\)","\\(n_{.C}\\)"),
f= c("\\(n_{1.}\\)","\\(n_{2.}\\)","...","\\(n_{L.}\\)","\\(N\\)"))
kable(text_tbl, "html", booktabs = T, col.names = c("","1","2","...","C"," "), escape=F) %>%
kable_styling(full_width = F,bootstrap_options = "striped") %>%
add_header_above(c(" Variável A", "Variável B" = 4, " ")) %>%
column_spec(1, bold = T) %>%
column_spec(2)

How to color one cell with kableExtra

I am just trying to highlight one cell in my table with kableExtra. The issue that I am having is that some of my cells have $s and ()s. Here is what it looks like
df3 <- data.frame(
"Bitcoin Price:" = c("Snow Panther B1+", "ASICminer 8 nano", "S9", "Avalon 921", "Dragonmint T1", "Edit E11++"),
"3000" = c("($270.71)", "($3376.85)", "($115.80)", "($530.81)", "($1108.14)", "($1035.42)"),
"6000" = c("$1050.37", "($1004.31)", "$666.06", "$547.62", "($245.39)", "$1337.12"),
"9000" = c("$2371.44", "$1368.24", "$1447.92", "$1626.04", "$617.35", "$3709.66"),
stringsAsFactors = FALSE, check.names=FALSE)
I have tried this but it doesn't work
df3 %>%
mutate(
`6000`[,2] = cell_spec(`6000`[,2], color = "red", bold = T)
) %>%
select("Bitcoin Price:", everything()) %>%
kable(align = "c", escape = F) %>%
kable_styling("hover", "striped", full_width = F) %>%
add_header_above(c(" " = 1, "Current Difficulty" = 3)) %>%
add_footnote(c("Statistics Calculated 2019"), notation = "symbol")
Does anyone have any suggestions? I feel like I am close. I am trying to make the cells with the value ($1004.31), red.
Is this what you are looking for?
df3 %>%
mutate(`6000` = cell_spec(`6000`, "html",color = ifelse(`6000` == "($1004.31)", "red", "grey"))) %>%
select("Bitcoin Price:", everything()) %>%
kable(align = "c", escape = F) %>%
kable_styling("hover", "striped", full_width = F) %>%
add_header_above(c(" " = 1, "Current Difficulty" = 3)) %>%
add_footnote(c("Statistics Calculated 2019"), notation = "symbol")

LaTex table in knitr with complex structure (rotating multirow text, removing column separators)

I need to create a latex table in RStudio for pdf output with the following structure:
This table was created for html output with the following code:
mat <- data.frame(a = c("column header","column header"),
rowx=c("row1","row2"),b = c("a","b"),
c = c("x","y"))
kable(mat, align = "c",col.names = c("","","v1","v2")) %>%
kable_styling(bootstrap_options = "striped", full_width = F,
position = "left",font_size = 12) %>%
column_spec(1, bold = T,width="2em",extra_css="transform: rotate(-90deg);") %>%
collapse_rows(columns = 1, valign = "middle") %>%
add_header_above(c(" " = 2, "row header" = 2))
I need to create a similar structure with LaTeX tables.
His is how far I got:
mat <- data.frame(a = c("column header","column header"),
rowx=c("row1","row2"),b = c("a","b"),c = c("x","y"))
kable(mat, align = "c",col.names = c("","","v1","v2")) %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left",font_size = 12) %>%
collapse_rows(columns = 1, latex_hline = "none") %>%
add_header_above(c(" " = 2, "rows" = 2))
So I still need at least 2 more things:
rotate the label in the very first column
remove the spurious leftmost column separator in the second row.
Can this be achieved with kableExtra commands and parameters?
Here's a shot with huxtable (my package):
as_hux(mat, add_colnames = TRUE) %>%
insert_row(c("", "", "rows", "")) %>%
merge_cells(3:4, 1) %>%
merge_cells(1, 3:4) %>%
merge_cells(1:2, 1:2) %>%
set_rotation(3, 1, 90) %>%
set_bottom_border(0.4) %>%
set_bold(1:2, everywhere, TRUE) %>%
set_wrap(3, 1, TRUE) %>%
set_bottom_padding(4, -1, 48) %>%
set_bottom_padding(3, -1, 30) %>%
set_row_height(c("1em", "1em", "1.5em", "1.5em")) %>%
quick_pdf()
I have to admit, this took a lot of tweaking. TeX tables are hard to understand....

Resources