Specify Column With in R's gtsummary with tbl_cross? - r

I am creating a cross-tabulation table in R with the tbl_cross funtion using #daniel-d-sjoberg's gtsummary package. I am trying to figure out how to specify the output column widths with gtsummary so I can modify the width of the first column in the table. In addition, I want to take advantage of gtsummary's formatting options like bolding and breaking table captions over two lines (by specifying " \n" in the modify_caption statement). The problem is, I can't seem to break a caption over multiple lines AND specify a column width. My starting point was to use the following code, which breaks the caption, correctly, onto two lines:
library(tidyverse)
library(flextable)
library(gtsummary)
mytable <- iris %>%
mutate(Long.Petal = ifelse(Petal.Width > .2, "Yes", "No")) %>%
tbl_cross(
row = Long.Petal,
col = Species,
percent = "cell"
) %>%
modify_caption("This is line 1 \n This is lin 2")
This outputs the following table:
After reviewing the documentation, it looks like the only way I can find to modify the column widths is by converting the table to a flextable using gtsummary's as_flex_table and then specifying the column widths. So, to do this, I modified the code above to chane the width of the first column to 3 inches by adding two additional lines of code as indicated in the comments in the revised code below:
library(tidyverse)
library(flextable)
library(gtsummary)
mytable <- iris %>%
mutate(Long.Petal = ifelse(Petal.Width > .2, "Yes", "No")) %>%
tbl_cross(
row = Long.Petal,
col = Species,
percent = "cell"
) %>%
modify_caption("This is line 1 \n This is lin 2") %>%
as_flex_table() %>% #NEW CODE LINE 1
width(., 1, 3) #NEW CODE LINE 2
mytable
This code produces the output below, which has now incorrectly placed lines 1 and 2 of the table caption onto a single line.
Is there a way, preferably in gtsummary with tbl_cross or its options to specify the column widths AND break a table caption across multiple lines?

We may use set_caption from flextable
iris %>%
mutate(Long.Petal = ifelse(Petal.Width > .2, "Yes", "No")) %>%
tbl_cross(
row = Long.Petal,
col = Species,
percent = "cell"
) %>%
as_flex_table() %>%
set_caption(caption = "This is line 1 <br/>This is line 2",
html_escape = FALSE)
-output

After the helpful suggestions from both #akrun and #daniel-d-sjoberg, I was able to get a version of this working and output to Word in Quarto using the following code:
---
title: "Untitled"
format: docx
editor: visual
#filters:
# - docx-landscape.lua
---
```{r}
#| echo: false
#| message: false
library(tidyverse)
library(flextable)
library(gtsummary)
mytable <- iris %>%
mutate(Long.Petal = ifelse(Petal.Width > .2, "Yes", "No")) %>%
tbl_cross(
row = Long.Petal,
col = Species,
percent = "cell"
) %>%
as_flex_table() %>% #NEW CODE LINE 1
width(., 1, 1) %>% #NEW CODE LINE 2
set_caption(
as_paragraph(
as_chunk("caption \n caption 2", props = fp_text_default(font.family = "Cambria"))
), word_stylename = "Table Caption")
mytable
```
This produced:
Thanks for everyone's help!
UPDATE
After #TarJae's answer, I realized this solution doesn't support summary statistics in the captions from the gtsummary package. So, I've decided to slightly modify this solution and provide one that will allow the user to include these. This can be accomplished as follows:
library(gtsummary)
library(tidyverse)
library(flextable)
#| echo: false
mytemptable<-iris %>%
mutate(Long.Petal = ifelse(Petal.Width > .2, "Yes", "No")) %>%
tbl_cross(
row = Long.Petal,
col = Species,
percent = "cell"
) %>%
modify_caption("First Line of the Caption \n Second Line with the total sample size is {N}")
mytemptable %>%
as_flex_table() %>%
set_caption(
as_paragraph(
as_chunk(mytemptable$table_styling$caption[1], props = fp_text_default(font.family = "Cambria"))
), word_stylename = "Table Caption")
All I've done here is to initially generate the label using gtsummary. Then I convert the table to a flextable and pull in the flextable caption from the caption generated by by it (i.e., mytemptable$table_styling$caption1, in the example above).

Thanks to the hint of #DanielD.Sjoberg now we can do it this way. We first must transfer the gt_summary tbl to a gt object using as_gt() (and not only gt() -> this won't work) then we can use cols_width() function:
What is also important to select the correct column we could do:
taken from #DanielD.Sjoberg comment above:
"first column is named label. You can see all the underlying colnames with show_header_names(). There are a bunch of hidden columns ,so we can reference the column by their index number.
See here https://gt.rstudio.com/reference/cols_width.html
library(tidyverse)
library(gtsummary)
library(gt)
iris %>%
mutate(Long.Petal = ifelse(Petal.Width > .2, "Yes", "No")) %>%
tbl_cross(
row = Long.Petal,
col = Species,
percent = "cell"
) %>%
modify_caption("This is line 1 \n This is lin 2") %>%
as_gt() %>%
cols_width(
"label"~ px(250)
)

Related

R: Use information from column of dataframe for caption in KableExtra

Using gt() you can make the title include information from the data frame in addition to text:
table_name <- paste(data$`column_data`[1],paste("Sample Text"))
table <- gt(data,
rownames_to_stub = TRUE) %>%
tab_header(title = table_name)
Is there a way to make KableExtra do this?
Yes, by supplying a data frame to the header argument of add_header_above() function. According to the documentation of this argument:
Alternatively, a data frame with two columns can be provided: The first column should
contain the header names (character vector) and the second column
should contain the colspan (numeric vector).
A {gt} table
mtcars |>
head(c(5,4)) |>
gt(rownames_to_stub = TRUE) |>
tab_header(paste(mtcars$drat[1], paste("Sample Text")))
The result:
A {kableExtra} table
mtcars |>
head(c(5,4)) |>
kable() |>
kable_styling(full_width = FALSE) |>
add_header_above(
data.frame(
text = paste(mtcars$drat[1],"Sample Text"),
span = 5)) # The number 5 is used to match the number of columns
The result:

How to display LaTeX symbols in Flextable (R)

I have generated the following table using the Flextable package in R. I created a conditionally formatted column with LaTeX arrow symbols in it, however the symbols aren't displayed when I generate it as a flextable. Is there a way to fix this?
library(tidyverse)
library(flextable)
data.frame(one = c(10,20,30), two = c(30,20,6)) %>%
mutate(Trend = case_when(.[,2] == .[,1] ~ "$\\rightarrow$", .[,2] > .[,1] ~ "$\\nearrow$", TRUE ~ "$\\searrow$")) %>%
flextable()
It may be easier to do this with unicode values for the symbols
library(dplyr)
library(flextable)
data.frame(one = c(10,20,30), two = c(30,20,6)) %>%
mutate(Trend = ifelse(two == one, "\U2192", "\U2190")) %>%
flextable()
-output

Rows not grouping in LaTeX rendering with pander

When I render the following table as HTML, I get expected row grouping:
library(expss)
library(dplyr)
library(pander)
library(knitr)
test_data =
data.table(
division = c(rep("A",5),rep("B",5)),
group = rep(c(rep("alpha",2),rep("beta",3)),2),
subgroup = c("red","orange","yellow","green","blue",
"indigo","violet","black","white","brown"),
ins = rnorm(10),
outs = runif(10),
overs = seq(1,100,10)
)
test_data = apply_labels(test_data,
division = "Department",
group = "Center",
subgroup = "Team",
ins = "In-flow",
outs = "Out-flow",
overs = "Throughput")
test_table =
test_data %>%
tab_cells(ins,
outs,
overs) %>%
tab_cols(division %nest% group %nest% subgroup) %>%
tab_stat_fun(identity) %>%
tab_pivot() %>%
drop_rc() %>%
tab_transpose()
test_table
However, when I render it as a PDF, the row grouping fails, replaced with long strings of pipe-delimited characters.
pander(test_table)
I think this is more of a LaTeX than R problem, but I'm not sure if it doesn't lie in the middle with pander. I would prefer to output this as a PDF, given preferences from folks "up the ladder".
Default output of the expss doesn't support pdf/latex. But there is an excellent package huxtable which works with pdf:
So you need to use as_huxtable:
library(huxtable)
as_huxtable(test_table)

tables rmarkdown cellpadding

I am trying to make a table using either hwrite or xtable in rmarkdown to produce a html table. I have been unable to use a cellpadding or cellspacing option, this is the code I am using and attached is a photo of the output.
{r, echo = FALSE, results = 'asis'}
cat(hwrite(sd.m.table, row.names = FALSE, cellpadding = 10, row.style = list("font-weight:bold")))
Using xtable() similarly did not work as well. Does anyone have suggestions?
Generated output from code
I'm not familiar with the hwriter package, and I rarely use xtable anymore (because I get frustrated with customizing tables), so I can't give you specific advice on using those.
I'm most comfortable with pixiedust (because I wrote it), but the htmlTable and tableHTML packages produce nice HTML tables and are probably worth looking into as well.
Working example with pixiedust
---
title: "Untitled"
output: html_document
---
```{r}
library(pixiedust)
head(mtcars) %>%
dust() %>%
sprinkle(pad = 10) %>%
medley_all_borders()
```
EDIT:
To get the appearance you are seeking with your data, try using
library(pixiedust)
library(dplyr)
DF <-
data.frame(rep_complete_time = c("2017-01-04 08:58:22",
"2017-01-04 08:58:33",
"2017-01-06 11:35:28"),
result = c(4.99184, 4.07356, 5.01569),
body_fluid = c("Serum", "Serum", "Serum"),
result_type = c("QC", "QC", "QC"),
fluid_lot = c(4426, 4426, 4426),
level = c(1, 1, 1))
DF %>%
# for some reason, sprintf results aren't holding when used in a
# sprinkle. This seems like a bug in pixiedust.
mutate(result = sprintf("%0.1f", result)) %>%
dust() %>%
sprinkle_colnames("Rep Complete Time", "Result", "Body Fluid",
"Result Type", "Fluid Lot", "Level") %>%
# use part = "table" to apply borders to all parts of the table.
# by default, pixiedust only wants to work with the body of the table.
medley_all_borders(part = "table") %>%
# using the sprinkle_table function can apply sprinkles to all of the
# parts of a table.
sprinkle_table(pad = 10,
halign = "left")
I wasn't able to replicate your alignment problem. All of the columns in my results are aligned left.

Format Numbers in FlexTable

I am using ReporteRs to generate a flexTable using the following piece of code:
library( ReporteRs )
baseCellProp <- cellProperties( padding = 2 )
baseParProp <- parProperties(text.align = "center")
ft.list <- list(mua= 1, mub = 2, mug = 1e-7)
ft.data <- t(data.frame(ft.list))
ft.FlexTable <- FlexTable( data = ft.data,
add.rownames = TRUE,
header.columns = FALSE,
body.cell.props = baseCellProp,
body.par.props = baseParProp)
ft.FlexTable <- setFlexTableWidths(ft.FlexTable, widths =c(1,2))
ft.FlexTable
The problem I am having is all the numbers are coming out in scientific notation like this:
mua 1e+00
mub 2e+00
mug 1e-07
Is there a way to tell flexTable how to format numbers? Specifically do not apply the same format to all the rows, but apply a format that makes sense on a row-by-row basis?
I solved this problem using flextable in R Markdown document by adding set_formatter_type and controlling how all my double data type are presented. My output was padding everything with lots of zeros that I did not want.
```{r echo=FALSE, message=FALSE, warning=FALSE, results='asis'}
library(flextable)
library(tidyverse)
results <- as.tibble(read.csv("D:/ALLRESULTS.csv",header=TRUE))
results %>% na.omit() %>% filter(grepl("KEY-K",Alignment)) %>%
arrange(Year,Source) %>%
select(Source,Question,Year,Target,Actual,Highest,n) %>%
regulartable() %>%
set_formatter_type(fmt_double="%.01f") %>%
align(part="header",align="center") %>%
align(align="left") %>% autofit()
```
I solved my problem using a hint from r transposing a data frame. The problem was transposing a data frame frame coerces all the elements to characters. Using matrices solves that problem:
ft.list <- list(mua= 1, mub = 2, mug = 1e-7)
ft.data <- as.matrix(ft.list, rownames.force=TRUE )

Resources