Most collaborators prefer tables in word format. With the advent of rmarkdown,knitr,gtsummary and flextable this is finally coming of age, but I cannot wrap my head around how I can generate the final table below without resorting to manually setting the indentation. I think table I below leaves far too much air between the rows, but I cannot figure out how to set the row spacing tighter programmatically (tried autofit, height, height_all, hrule without obtaining desired output). Instead, I used the compact style in word to generate tbl 2 below. However, then I´d have to manually insert the indentation for the cyl categories. Anyone know how this can be done programmatically?
title: "testing T´s"
output:
word_document:
reference_docx: temp.docx
html_document:
df_print: paged
editor_options:
chunk_output_type: inline
---
Plain
====
```{r results='asis',echo=FALSE,message=FALSE}
library(gtsummary)
library(flextable)
set_gtsummary_theme(theme_gtsummary_jama())
a <- mtcars[1:20,c(1,2,9,4)]
b <- tbl_summary(a,
missing="ifany",
by=am,
type=list(cyl~"categorical"))%>%
bold_labels() %>%
add_p() %>% add_overall()
```
Flextable
====
```{r results='asis',echo=FALSE,message=FALSE}
fl <- gtsummary::as_flextable(b) %>% font(fontname = "Bodoni 72",part = "all") %>% fontsize(size=8,part="all") %>% autofit(add_h = -.5)
fl
```
At the moment, there is no simple way to do this. But I have included a code example that I think does solve your problem.
With {flextable} it's important the order the functions are called. Running as_flextable() then appending additional calls doesn't seem to get you what you want.
The alternative is save the calls, insert the new flextable function calls where needed, then evaluate the calls. That is what is done in the example below.
---
title: "Untitled"
output: word_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, message = FALSE)
```
```{r}
library(tidyverse)
library(gtsummary)
library(flextable)
set_gtsummary_theme(theme_gtsummary_jama())
tbl <-
mtcars[1:20, c(1, 2, 9, 4)] %>%
tbl_summary(
missing = "ifany",
by = am,
type = list(cyl ~ "categorical")
) %>%
bold_labels() %>%
add_p() %>%
add_overall()
```
### Default Flextable
```{r}
gtsummary::as_flextable(tbl)
```
### Compact Flextable
```{r}
# this function inserts additional flextable calls, then evaluates the calls
update_flextable_calls <- function(x, call_list, after) {
# saving calls that create the flextable
x_calls <- gtsummary::as_flextable(x, return_calls = TRUE)
# adding new calls at `after=`
after_n <- names(x_calls) %in% after %>% which()
x_calls <- c(
x_calls[1:after_n],
call_list,
x_calls[(after_n + 1):length(x_calls)]
)
# evaluating calls
x_calls %>%
unlist() %>%
purrr::compact() %>%
# concatenating expressions with %>% between each of them
purrr::reduce(function(x, y) rlang::expr(!!x %>% !!y)) %>%
# evaluating expressions
eval()
}
# list of calls that make a table compact
compact_calls <- list(
rlang::expr(font(fontname = "Bodoni 72", part = "all")),
rlang::expr(fontsize(size = 8, part = "all")),
rlang::expr(padding(padding.top = 0, part = "all")),
rlang::expr(padding(padding.bottom = 0, part = "all"))
)
# adding the compact calls, and evaluating them
update_flextable_calls(
x = tbl, # gtsummary table
call_list = compact_calls, # calls that make flextable compact
after = "footnote" # add calls after the "footnote" functions
)
```
This obviously isn't a great permanent solution. We have a theme called theme_gtsummary_compact() that makes the {gt} tables compact with smaller font and reduced padding. We can update the theme to also make flextables more compact! I'd love it if you created an issue on GitHub to update theme_gtsummary_compact() for flexables, and we can collaborate on a solution that works well for you.
https://github.com/ddsjoberg/gtsummary/issues/new/choose
Related
I'm using gtsummary to prepare my tables, I'm trying to hide one of the columns from the groups, the third column labeled as "1, N = 61"
Below is the code ran,
library(gtsummary)
trial <- trial
trial %>%
tbl_summary(by=response,
statistic = list(trt~"{n}/{N} ({p}%)")) %>%
add_overall() %>%
add_p() %>%
modify_column_hide(columns = "1")
The output provided
I was expecting that the third column would be hidden "1, N = 61"
The 2 columns (0 , 1) are named "stat_1" and "stat_2" respectively.
So, to hide the one you ask for:
trial %>%
tbl_summary(by=response,
statistic = list(trt~"{n}/{N} ({p}%)")) %>%
modify_column_hide(columns = "stat_2") %>%
add_p() %>%
add_overall()
Output:
Now, if you want to hide parameters of statistical tests you run, you would do it as indicated here:
https://rdrr.io/cran/gtsummary/man/modify_column_hide.html
What is the correct syntax to display both median and mean of a continuous variable using tbl_continuous? Also, is it possible to display on 2 lines as you can do with tbl_summary and the continuous2 argument?
Code below is just displaying medians (see image).
comparison.data %>%
select(imaging, los.minutes, acuity) %>%
tbl_continuous(
by = imaging,
variable = los.minutes,
statistic =
los.minutes ~ c("{mean} ({sd})",
"{median} ({sd})")
) %>%
modify_spanning_header(all_stat_cols() ~ "**Imaging status**")
Just displaying medians
Example below!
library(gtsummary)
packageVersion("gtsummary")
#> [1] '1.6.1'
tbl <-
trial %>%
tbl_continuous(
variable = age,
by = trt,
include = grade,
statistic = ~"{mean} \n{median}"
) %>%
as_gt() %>%
gt::fmt_markdown(columns = everything())
Created on 2022-08-24 by the reprex package (v2.0.1)
I'm trying to create some lm() models for every level of the categorical variable, from one dataframe.
I used function lm() with group_by, but it doesn't work, creating only one model.
Of course, it is easy to create each datasets and use lm() for each of these, but I want to know other way, using group_by, apply, etc.
make_model <- function(data){
lm(Sepal.Length~Sepal.Width,data)
}
models <- iris %>%
group_by(Species) %>%
make_model
predicted <- iris %>%
group_by(Species) %>%
mutate(prediction=predict(models,.))
I would check out the many models chapter of R for data science:
https://r4ds.had.co.nz/many-models.html
library(tidyverse)
make_model <- function(data){
lm(Sepal.Length~Sepal.Width,data)
}
iris %>%
group_by(Species) %>%
nest() %>%
mutate(lm = map(data,
make_model)) %>%
mutate(tidy = map(lm,
broom::tidy)) %>%
unnest(tidy)
Is there a way to add the Statistic for each variable as a column in a tbl_regresion() with {gtsummary}? In Psychology is not uncommon for reviewers to expect this column in the tables.
When using {sjPlot}, just need to add the show.stat parameter, and the Statistic column will appear showing the t value from summary(model).
library(gtsummary)
library(sjPlot)
model <- lm(mpg ~ cyl + wt, data = mtcars)
tab_model(model, show.stat = TRUE)
With {gtsummary} I can't find anywhere how to add an equivalent column when using tbl_regression(). Would just want to show a column with the values already present in the model.
library(gtsummary)
model <- lm(mpg ~ cyl + wt, data = mtcars)
stats_to_include =c("r.squared", "adj.r.squared", "nobs")
tbl_regression(model, intercept = TRUE, show_single_row = everything()) %>%
bold_p() %>%
add_glance_table(include = all_of(stats_to_include))
Yep! The statistic column is already in the table, but it's hidden by default. You can unhide it (and other columns) with the modify_column_unhide() function. Example below!
library(gtsummary)
packageVersion("gtsummary")
#> [1] '1.5.2'
model <- lm(mpg ~ cyl + wt, data = mtcars)
tbl <-
tbl_regression(model, intercept = TRUE, show_single_row = everything()) %>%
bold_p() %>%
add_glance_table(include = c(r.squared, adj.r.squared, nobs)) %>%
modify_column_unhide(columns = c(statistic, std.error))
Created on 2022-02-07 by the reprex package (v2.0.1)
FYI if you're interested, we also support journal themes in gtsummary. You can, for example, load the JAMA theme and the gtsummary results will be auto-formatted for publication in JAMA. We don't have Psychology theme, but if you file a GitHub Issue, we can collaborate on adding one. We can add things like showing the statistic column by default (and much more).
https://www.danieldsjoberg.com/gtsummary/reference/theme_gtsummary.html
The following code produces an N column of "N" and "Event N" as part of the univariate regression table.
I have a case control dataset and I would like to have the columns "Cases" and "Controls" giving the numbers of cases and controls instead.
The "cases" and "control" are in determined by the variable "response" in the code below. e.g. response(1) = "cases", while response(0) = "controls".
How can I do this?
thanks,
nelly
tbl_uv_nevent_ex <-
trial[c("response", "trt", "age", "grade")] %>%
tbl_uvregression(
method = glm,
y = response,
method.args = list(family = binomial)
) %>%
add_nevent()
You can do this by adding the number of controls to the .$table_body data frame. I've included an example below. There is a sticking point at the moment....after you add the number of controls to the data frame that will be printed, we need to add the new column to the internal set of instructions to print in gtsummary. This step is a headache now, but we're working on a solution to make it accessible to users. Here is the first draft of that function: http://www.danieldsjoberg.com/gtsummary/dev/reference/modify_table_header.html
In the meantime, here's how you can get that done:
library(gtsummary)
tbl <-
trial[c("response", "trt", "age")] %>%
tbl_uvregression(
method = glm,
y = response,
method.args = list(family = binomial),
exponentiate = TRUE
) %>%
add_nevent()
# add the number of controls to table
tbl$table_body <-
tbl$table_body %>%
dplyr::mutate(
n_nonevent = N - nevent
) %>%
dplyr::relocate(n_nonevent, .after = nevent)
# updating internal info with new column (this part will not be required in the future)
tbl$table_header <-
gtsummary:::table_header_fill_missing(tbl$table_header,
tbl$table_body)
# print tbl with Case and Control Ns
tbl %>%
modify_header(
list(nevent ~ "**Case N**",
n_nonevent ~ "**Control N**")
)