larmarange / ggstats

Extension to ggplot2 for plotting stats
https://larmarange.github.io/ggstats/
GNU General Public License v3.0
29 stars 1 forks source link

Add a coefficient table to the ggcoef_model() output #32

Closed mathewrm closed 1 year ago

mathewrm commented 1 year ago

The output plot of ggcoef_* functions are good. I would also love to see an option that allows users to specify whether or not to include a table which shows coefficient estimates (e.g. OR) and confidence intervals corresponding to each term in the model.

Here is an example of what I mean (although the code could use a significant improvement for more flexible customizability):

attach trial data from gtsummary package

data(trial, package="gtsummary")

fit a logistic regression model

glm_model <- glm( response ~ rms::rcs(age, 3) + trt*grade + marker + stage, data = trial, family = binomial )

define a function to attach a coefficients table to ggcoef_model output

ggcoef_table <- function(model) {
  #library(tidyverse)
  coef_data <- ggstats::ggcoef_model(
    model = model, 
    exponentiate = TRUE,
    return_data = TRUE
  )

  coef_plot <- ggstats::ggcoef_model(
    model = model,
    exponentiate = TRUE,
    show_p_values = FALSE,
    signif_stars = FALSE
  )

  coef_data <- coef_data %>% 
    dplyr::mutate(across(c(estimate, conf.low, conf.high), \(x) round(x, 1))) 

  coef_data_table <- coef_data %>% 
    dplyr::mutate(
      estimate = as.character(estimate),
      conf_interval = paste0(conf.low, ", ", conf.high)
    ) %>% 
    tidyr::pivot_longer(
      c(estimate, conf_interval), 
      names_to = "stat",
      names_transform = list(stat = as.factor)
    ) %>% 
    dplyr::mutate(
      stat = fct_relevel(stat, c("estimate", "conf_interval"))
    )

  coef_data_table_plot <- coef_data_table %>% 
    ggplot2::ggplot(
      aes(
        x = stat, 
        y = term,
        label = value
      )
    ) +
    ggplot2::geom_text(hjust = 1, size = 3) +
    ggplot2::scale_x_discrete(position = "top", labels = c("OR", "95% CI")) +
    ggplot2::scale_y_discrete(limits = rev) + # reverse factor levels to align estimates with corresponding terms
    ggplot2::labs(
      y = NULL, 
      x = NULL
    ) +
    cowplot::theme_cowplot() +
    ggplot2::theme(
      # customize theme to have a clear background for the text
      panel.grid.major = element_blank(),
      axis.line = element_blank(),
      axis.ticks = element_blank(),
      axis.text.y = element_blank(),
      axis.text.x = element_text(face = "bold", hjust = 1),
      strip.text = element_blank()
    )

  # join the plots
  coef_plot + patchwork::plot_spacer() + coef_data_table_plot + patchwork::plot_layout(widths = c(4, -0.5, 3))
}

use custom function on fitted model ggcoef_table(model = glm_model)

image

larmarange commented 1 year ago

It could be a good idea. Let me explore it and try to prepare PR

larmarange commented 1 year ago

Could you have a look at #33?

library(ggstats)
mod <- lm(Sepal.Length ~ Sepal.Width + Species, data = iris)
ggcoef_table(mod)

ggcoef_table(mod, table_stat = c("estimate", "ci"))

ggcoef_table(mod, table_witdhs = c(1, 1), table_text_size = 5)

ggcoef_table(mod, stripped_rows = FALSE)


d_titanic <- as.data.frame(Titanic)
d_titanic$Survived <- factor(d_titanic$Survived, c("No", "Yes"))
mod_titanic <- glm(
  Survived ~ Sex * Age + Class,
  weights = Freq,
  data = d_titanic,
  family = binomial
)
ggcoef_table(mod_titanic, exponentiate = TRUE)


# display only a subset of terms
ggcoef_table(mod_titanic, exponentiate = TRUE, include = c("Age", "Class"))

Created on 2023-08-01 with reprex v2.0.2

mathewrm commented 1 year ago

I've tried the code and it works as expected. Kudos!