kable indent rows with specific hspace for all columns - r

The following code add indentations to the 2nd & 4th rows for first column only.
library(kableExtra)
knitr::kable(head(mtcars[ ,1:4]), "latex") %>%
add_indent(positions = c(2, 4))
Wondering how to add indentations of specific hspace to the 2nd & 4th rows for all columns. Something like this
library(kableExtra)
knitr::kable(head(mtcars[ ,1:4]), "latex") %>%
add_indent(positions = c(2, 4), hspace = "2em", allCols = TRUE)

add_indent is indeed only made for the first column.
A workaround would be to add the indentation manually in your data frame:
head(mtcars) %>%
mutate_all(., funs(ifelse(row_number() %in% c(2, 4),
paste0("\\hspace{1em}", .), .))) %>%
kable(format = "latex", booktabs = T, escape = F)
gives:

We can write a version of the add_indent function that adds this option. Doing it this way ensures that kable options such as digits are applied consistently in each row.
add_indent = function(kable_input, positions, allCols = FALSE) {
out = kableExtra::add_indent(kable_input, positions)
if (allCols){
table_info <- magic_mirror(kable_input)
for (i in positions + table_info$position_offset) {
rowtext <- table_info$contents[i]
table_info$contents[i] <- gsub(' &', paste(' &', kableExtra:::latex_indent_unit('')), rowtext)
out <- gsub(rowtext, table_info$contents[i], out, fixed = T)
}
out <- structure(out, format = "latex", class = "knitr_kable")
attr(out, "kable_meta") <- table_info
}
return(out)
}
kable(head(mtcars[ ,1:4]), "latex", align = 'l') %>%
add_indent(positions = c(2, 4), allCols = T)

Related

r kable replace 0.0 with blank or "-" and keep it as numeric

I have this little table:
cases <- c("1182025", "+19525")
deceased <- c("7639", "+25")
TI_7 <- c(1100.395332, 0.0)
df <- data.frame(cases, deceased, TI_7)
If I kable it, the 0.0 in the third column should not appear.
If possible, the data type of the third column should remain numeric, otherwise decimal.mark = ',' does not work.
This is how I kable:
kbl(df, format.args = list(decimal.mark = ',', digits=6), align = "rccc") %>%
kable_paper(bootstrap_options = "striped", full_width = F, position = "left")
I tried it with gsub, but then all the 0s disappear, inside the numbers too.
With other functions the data type changes to unknown.
Ok this seems to work:
df <- na_if(df, 0)
options(knitr.kable.NA = '')
kbl(df, format.args = list(decimal.mark = ',', digits=6), align = "rccc") %>%
kable_paper(bootstrap_options = "striped", full_width = F, position = "left")

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

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....

adding images to flextable using Display() & as_image() in loop doesnot work

I have a zip file which has multiple images of 2 types.1 -FrequencyRose images 2- EnergyRose images. I have created a flextable and then replacing the even rows with images and odd rows with the image titles using for loop . The loop is correctly displaying the titles but its only printing the last read image of each type mulitple times instead of actually printing all the images as per loop count.
img.file <- unzip("D:\\Mast_Image Files.zip")
fr_files <- img.file[grepl(paste("FrequencyRose", collapse = "|"), img.file)]
er_files <- img.file[grepl(paste("EnergyRose", collapse = "|"), img.file)]
fr_files has 3 image file paths and same with er_files
click
num_masts = length(img.file)
c1 = rep("Freq_rose",num_masts)
c2 = rep("Energy_Rose",num_masts)
df = data.frame(c1,c2)
dfft = flextable(df)
sso=seq(1,num_masts,2)
sse=seq(2,num_masts,2)
for (g in 1:(num_masts/2)){
ff.img = fr_files[g]
ef.img = er_files[g]
dfft2 = dfft %>%
display(
i = sse[g], col_key = "c1", pattern = "{{img}}",
formatters = list( img ~ as_image(c1,
src = ff.img, width = 3, height = 3))) %>%
display(
i = sse[g], col_key = "c2", pattern = "{{img}}",
formatters = list( img ~ as_image(c2,
src = ef.img, width = 3, height = 3))) %>%
display(
i = sso[g], col_key = "c1", pattern = paste("Freq_Rose","mast",g)) %>%
display(
i = sso[g], col_key = "c2", pattern = paste("Energy Rose","mast",g))
}
this loop is able to produce titles correctly but the only the fr_files[3], er_files[3] is looping over all the even rows of corresponding columns. output is as :final results . could not find the issue.
I can't reproduce your example (I don't have the images).
library(ggplot2)
library(tidyverse)
library(flextable)
# a data example ----
zz <- iris %>%
group_by(Species) %>%
summarise( n = n(), avg = mean(Petal.Length),
img_path = paste0( unique(as.character(Species)), ".png"),
gg = list(ggplot(tibble(Sepal.Length, Petal.Width), aes(Sepal.Length, Petal.Width)) + geom_point() + theme_minimal())
)
zz
# create the png ----
walk2(zz$gg, zz$img_path, function(gg, path){
png(filename = path, width = 300, height = 300)
print(gg)
dev.off()
})
From there you have everything you need and the flextable commands could be:
# create the flextable -----
flextable(zz, col_keys = c("Species", "n", "avg", "plot")) %>%
# here, i is selecting only odd rows
compose(i = ~ seq_along(Species) %% 2 > 0, j = "plot", value = as_paragraph(as_image(img_path, width = 300/72, height = 300/72))) %>%
theme_box() %>%
autofit()

kable/kableExtra Add superscript to group labels in group_rows

I have a table that I am creating for a pdf presentation using kable and kableExtra. I am wanting to group the rows and I need to use superscripts in the row group labels. I have tried several different things. Here is an example of some of the methods I have tried so far.
library(kable)
library(kableExtra)
foo <- data.frame(a = 1:10, b = 11:20, c = 21:30)
kable(foo, format = "latex", booktabs = T, row.names = FALSE, linesep = "", escape = FALSE) %>%
kable_styling(latex_options = c("striped")) %>%
group_rows("Group1<sup>a</sup>", 1, 2) %>%
group_rows(paste0("Group2", footnote_marker_alphabet(1), sep = ""), 3, 4) %>%
group_rows(expression("Group3"^a), 5, 6) %>%
group_rows("Group4\\textsuperscript{a}", 7, 8)
I have run out of ideas and haven't been able to find any additional suggest in my search.
You need escape=FALSE in your group_rows() calls to allow the latex commands to be interpreted. You also seem to need to double each backslash (I don't quite understand why). After that, there are a few different options that work:
kable(foo, format = "latex", booktabs = T, row.names = FALSE, linesep = "", escape = FALSE) %>%
kable_styling(latex_options = c("striped")) %>%
group_rows("$\\\\text{Group1}^a$", 1, 2, escape = FALSE) %>%
group_rows(paste0("Group2\\\\", footnote_marker_alphabet(1), sep = ""), 3, 4, escape = FALSE) %>%
# I don't think expression() is helpful, doesn't seem to get converted
# to latex
group_rows(expression("Group3"^a), 5, 6) %>%
group_rows("Group4\\\\textsuperscript{a}", 7, 8, escape = FALSE)

Resources