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")
Related
I am listing my results in RMarkdown. I want to show max values in each column in bold. How can I do that?
See the code, and output (as png) below please.
data<-data.frame(A=c(1,2,4,3), B=c(8,7,9,10), C=c(14,12,13,11), D=c(15,18,17,16))
rownames(data)<-c("E", "F", "G", "H")
library(knitr)
library(kableExtra)
kable(data) %>%
kable_styling(
full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed"),
) %>%
add_header_above(c( '', Group1 = 2, Group2 = 2))
We could do this with cell_spec
Loop across the columns of the dataset, add the cell_spec layer with bold argument as a logical vector i.e. TRUE where the column value is max with ==
Convert to kable and use the OP's code as in the post
library(dplyr)
library(knitr)
library(kableExtra)
data %>%
mutate(across(everything(), ~ cell_spec(., bold = . == max(.)))) %>%
kable(escape = FALSE, booktabs = TRUE) %>%
kable_styling(
full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed"),
) %>%
add_header_above(c( '', Group1 = 2, Group2 = 2))
-output
If this needs to be by row maxs, then an option would be to transpose
data %>% t %>%
as.data.frame %>%
mutate(across(everything(), ~ cell_spec(., bold = . == max(.)))) %>%
t %>%
as.data.frame %>%
kable(escape = FALSE, booktabs = TRUE) %>%
kable_styling(
full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed"),
) %>%
add_header_above(c( '', Group1 = 2, Group2 = 2))
-output
Or for the rowwise, create the cell_spec layer with apply
data[] <- t(apply(data, 1, function(x) cell_spec(x, bold = x == max(x))))
data %>%
kable(escape = FALSE, booktabs = TRUE) %>%
kable_styling(
full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed"),
) %>%
add_header_above(c( '', Group1 = 2, Group2 = 2))
Or may use dapply from collapse for faster execution
library(collapse)
dapply(data, MARGIN = 1, FUN = function(x) cell_spec(x, bold = x == fmax(x))) %>%
kable(escape = FALSE, booktabs = TRUE) %>%
kable_styling(
full_width = FALSE,
bootstrap_options = c("striped", "hover", "condensed"),
) %>%
add_header_above(c( '', Group1 = 2, Group2 = 2))
In Rmd knit to pdf we found out we can end a table with a double line like this:
tibble(v1 = c(1:2),v2 = c(1:2)) %>%
kable(booktabs = TRUE) %>%
kable_styling(position = "left") %>%
row_spec(2, hline_after = TRUE) %>%
row_spec(3, hline_after = TRUE)
When we want to use this for a table that continues on the next page, with use of:
tibble(v1 = c(1:2),v2 = c(1:2)) %>%
kable(booktabs = TRUE, longtable = TRUE) %>%
kable_styling(latex_options = c("repeat_header"),
position = "left") %>%
row_spec(2, hline_after = TRUE) %>%
row_spec(3, hline_after = TRUE)
we see an unwanted * between the two lines. Does anyone know why the * appears, or have a suggestion how to get rid of the *, or a better solution to have a double line at the end of a table? Thanks!
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....
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))
First, the package kableExtra indeed produces awesome table. I just have an additional request :
When running this example ( from the manual)
iris[1:10, ] %>% select(-Species) %>%
mutate_if(is.numeric, function(x) {
cell_spec(x, "latex", bold = T, color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
}) %>%
kable("latex", escape = F, booktabs = T, linesep = "", align = "c")
The cells are formated in each column. (1) How to adjust them to the entire table ? (2) Or to a user defined scale ? I noticed that both kableExtra::spec_color and
kableExtra::cell_spec make use of the scales::rescale function which does take a from argument but it's not used in the functions.
Below code of reproducible .Rnw script.
\documentclass{article}
\usepackage[usenames,dvipsnames,svgnames,table]{xcolor}
\usepackage{booktabs}
\usepackage{float}
\usepackage{colortbl}
\begin{document}
<<tab10, echo=FALSE, results="as.is">>=
require(knitr)
require(kableExtra)
require(tidyverse)
#
<<tab1, echo=FALSE, results="as.is">>=
require(knitr)
require(kableExtra)
require(tidyverse)
iris[1:10, ] %>% select(-Species) %>%
mutate_if(is.numeric, function(x) {
cell_spec(x, "latex", bold = T, color = spec_color(x, end = 0.9),
font_size = spec_font_size(x))
}) %>%
kable("latex", escape = F, booktabs = T, linesep = "", align = "c")
#
\end{document}
Okay, with the latest dev ver, you can use scale_from in spec_color, spec_font_size & spec_angle.
library(kableExtra)
library(dplyr)
library(knitr)
iris[1:10, ] %>%
select(-Species) %>%
mutate_if(is.numeric, function(x) {
cell_spec(x, "latex", bold = T,
color = spec_color(x, end = 0.9, scale_from = range(unlist(iris[1:10, ]))),
font_size = spec_font_size(x, scale_from = range(unlist(iris[1:10, ]))))
}) %>%
kable("latex", escape = F, booktabs = T, linesep = "", align = "c")