gt Tables - applying formatting to multiple dataframes - r

I have several tables that all need to be formatted similarly. I figured out how I want the tables formatted on one table, and have been trying to write a function that I can apply to all tables easily without having to copy and paste the code over and over
Here is my sample data frame
example <- data.frame(
stringsAsFactors = FALSE,
age = c("age 12 to 17", "age 18 to 25", "age 26 and up"),
alc_est = c(14579.28558, 131872.35964, 660957.6512),
bing_alc = c(0.0477, 0.3143, 0.224),
marj_est = c(35913.3345, 137033.12968, 534667.52856),
mj_use = c(0.1175, 0.3266, 0.1812),
heroin_est = c(NA, 419.5748, 18294.36356),
heroin_use = c(NA, 0.001, 0.0062),
meth_est = c(550.16172, 2139.83148, 68161.25778),
meth_use = c(0.0018, 0.0051, 0.0231)
)
Here is some of the formatting that will be applied to multiple tables
table_format <- example %>%
gt(rowname_col = "age") %>%
tab_stubhead(label = md("**Statewide**")) %>%
tab_header(
title = md("**table title here**"),
subtitle = "more info here"
) %>%
fmt_number(
columns = c(2, 4, 6, 8),
decimals = 0
) %>%
tab_spanner_delim(
delim = "_",
columns = c(2:9)
)
Here is how I tried to write a function to apply to multiple tables. The function runs but doesn't actually format the table
format_use_est <- function(df_here) {
result <- df_here %>%
gt(rowname_col = "age") %>%
tab_stubhead(label = md("**Statewide**")) %>%
tab_header(
title = md("**table title here**"),
subtitle = "more info here"
) %>%
fmt_percent(
columns = c(3, 5, 7, 9),
decimals = 1
) %>%
fmt_number(
columns = c(2, 4, 6, 8),
decimals = 0
) %>%
tab_spanner_delim(
delim = "_",
columns = c(2:9)
)
}
How can I write a function for formatting these tables and apply to multiple tables more effectively? Thank you!

Related

Missing diacritics in GT table output

I am using GT package in R to create tables for my diploma thesis and I ran into a problem. The diploma is to be written in the czech language.
When GT draws the table it does not display the letter ě properly and shows e instead.
The code for GT table:
desc_sex[,2:ncol(desc_sex)] %>% gt(rowname_col = "sex"
) %>% tab_stubhead(
label = html("Kategorie")
) %>% cols_align(
align = "center",
columns = everything()
) %>% cols_label(
n = html("n"),
procent = html("%")
) %>% tab_row_group(
label = html("<b>Sledované regiony celkem"),
rows = 7:9
) %>% tab_row_group(
label = html("<b>Krajský soud v Ostravě"),
rows = 4:6
) %>% tab_row_group(
label = html("<b>Městský soud v Praze"),
rows = 1:3
) %>% summary_rows(
groups = T,
fns = list(
Celkem = ~sum(.)),
formatter = fmt_number,
decimals = 0
)
Here are the data in CSV compliant format:
"reg_reside","sex","n","procent","single"
"MSPH","Muž",93,46.5,52
"MSPH","Žena",83,41.5,34
"MSPH","Manželský pár",24,12,0
"KSOS","Muž",113,56.5,51
"KSOS","Žena",68,34,30
"KSOS","Manželský pár",19,9.5,0
"Celkem","Muž",206,51.5,103
"Celkem","Žena",151,37.8,64
"Celkem","Manželský pár",43,10.8,0
Here is how the output looks in GT - the mistake is in Ostrave (should be Ostravě) and Mestsky (should be Městský):
You can try using html entities like i.e. ě = &ecaron;
desc_sex[,2:ncol(desc_sex)] %>%
gt(rowname_col = "sex") %>%
tab_stubhead(label = html("Kategorie")) %>%
cols_align(align = "center",columns = everything()) %>%
cols_label(n = html("n"),
procent = html("%")) %>%
tab_row_group(label = html("<b>Sledované regiony celkem"),
rows = 7:9) %>%
tab_row_group(label = html("<b>Krajský soud v Ostrav&ecaron;"),
rows = 4:6) %>%
tab_row_group(label = html("<b>M&ecaron;stský soud v Praze"),
rows = 1:3) %>%
summary_rows(groups = T,
fns = list(Celkem = ~sum(.)),
formatter = fmt_number,
decimals = 0)

Adding Headers to a table using formattable in R

I would like to add headers entitled "Category 1", "Category 2", "Category 3" and "Category 4" to a table, separated by a black line. I would like it to look like the picture attached. Please see the code for the table without the Categories/black lines between columns:
library(formattable)
data(mtcars)
df <- mtcars
formattable(df)
Desired plot
Here is one with kable where can use add_header_above by passing a vector of key/value pair with key suggesting the name and value for the number of columns to be expanded
library(kableExtra)
library(dplyr)
library(kableExtra)
mtcars %>%
kable() %>%
kable_styling(bootstrap_options = "bordered",
full_width = FALSE) %>%
add_header_above(c("", "Category1" = 3, "Category2" = 3,
"Category3" = 3, "Category4" = 2)) %>%
collapse_rows(columns = 1,
valign = "middle")
-output
Some of the styling can be changed as well
mtcars %>%
kable() %>%
kable_styling(bootstrap_options = "responsive",
full_width = FALSE) %>%
add_header_above(c("", "Category1" = 3, "Category2" = 3,
"Category3" = 3, "Category4" = 2)) %>%
collapse_rows(columns = 1,
valign = "middle")

Allow duplicated names in binded tables

UPDATE for why I changed my votes.
This code has the table displayed but R doesn't knit pdf.
all_jt %>%
kbl(longtable = T, booktabs = T,
caption = "table") %>%
remove_column(7) %>%
add_header_above(c(" " = 2, "Year 1" = 4, "Year 2" = 4)) %>%
kable_styling(latex_options = c("repeat_header"))
Quitting from lines 13-37 (test_table.Rmd)
Error in remove_column(., 7) :
Removing columns was not implemented for latex kables yet
switching to select(-7) as in here Remove_Column from a kable table which will be output as latex/pdf doesn't work because R doesn't like duplicated column names.
I have two ANOVA tables, jt_1 and jt_2 below, that I want to merge and keep 1 column for the model term only. As I remove the duplicated column, R added .1 to the tail of columns' 7, 8, 9 and 10 names.
library(emmeans)
library(stringr)
warp.lm <- lm(breaks ~ wool * tension, data = warpbreaks)
jt_1 <- print(joint_tests(warp.lm), export = T) %>% as.data.frame()
jt_2 <- jt_1
all_jt <- cbind(jt_1, jt_2) %>%
setNames(gsub("summary.", "", colnames(.)))
all_jt[,-6]%>% #to remove the duplicated column for model term
data.frame(check.names = F) %>%
kbl(longtable = T, booktabs = T,
caption = "table") %>%
add_header_above(c(" " = 2, "Year 1" = 4, "Year 2" = 4)) %>%
kable_styling(latex_options = c("repeat_header"))
Here is a brief idea of what I need.
Many thanks in advance.
You can use remove_column function from kableExtra to remove a column instead of all_jt[,-6] which makes the column name unique.
library(knitr)
library(kableExtra)
all_jt %>%
kbl(longtable = T, booktabs = T,
caption = "table") %>%
remove_column(7) %>%
add_header_above(c(" " = 2, "Year 1" = 4, "Year 2" = 4)) %>%
kable_styling(latex_options = c("repeat_header"))
R does not like duplicate column names in data.frames. If you step through your last code block line by line you will notice that all_jt[, -6] makes column names unique by adding the ".1" suffix.
The/a solution is to provide column names to kbl directly, e.g.
all_jt[,-6] %>%
kbl(longtable = T, booktabs = T,
col.names = gsub("\\.\\d", "", names(.)),
caption = "table") %>%
add_header_above(c(" " = 2, "Year 1" = 4, "Year 2" = 4)) %>%
kable_styling(latex_options = c("repeat_header"))
This produces

How to remove/change decimal sum value in flextable

I managed to create a flextable based on the below code.
The data that is being used in opleiding1 through 4 looks a bit like this: 0, 0, 1, 7, 3, 7, 0
t7 <- data.frame(df$opleiding.1.[df$startvraag=="Ja"],
df$opleiding.2.[df$startvraag=="Ja"],
df$opleiding.3.[df$startvraag=="Ja"],
df$opleiding.4.[df$startvraag=="Ja"]
)
t7 <- data.frame(aantal=(apply(t7, 2, sum))) %>% round(digits = 0)
rownames(t7) <- c("hbo, universitair", "mbo, vwo, havo", "vmbo/mavo", "onbekend")
t7
Creating a flextable with the following code:
t7 <- xtable(t7)
ft7 <- t7 %>% xtable_to_flextable() %>%
fontsize(part = "header", size = 20) %>%
fontsize(part = "body", size = 18) %>%
align_text_col(align = "left") %>%
align_nottext_col(align = "center") %>%
width(width = 2.3) %>%
width(j = 1, width = 2.0) %>%
height_all(height = .5) %>%
border_inner(border = std_border) %>%
font(fontname = "Open Sans") %>%
color(part = "header", color = d) %>%
ft7
This gives me a flextable which is just as I want it except for the decimal which are shown here. I've looked for possible solutions but nothing seems to work. It looks like the decimal is added when converting the table to an flextable. When I run the previous code (mentions on top) it does not return with any decimals as shown here. Hope someone can help me sort this.
I think that is because your aantal column's type is double, meaning it is holding real values. You can change it's type to integer as you create the data.frame.
Try this
t7 <- data.frame(aantal=(apply(t7, 2, sum))) %>%
round(digits = 0) %>%
mutate(aantal = as.integer(aantal))

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