Search code examples
rr-markdownkableextra

Combining add_header_above and spec_pointrange to create a table with grouping


KableExtra has some really nice features that allows you to create tables and grouping columns using add_header_above as well as presenting visualisations in your table. Now, I wonder if it's possible to combine these two features? I want to create a table with grouped columns and visualisations at the same time.

So for example, let's say that example data 1 and 2 are the results from two different analyses, but with the same variables of interest, that I want to present in the same table but in different groups in line with this: https://cran.r-project.org/web/packages/kableExtra/readme/README.html.

Is there a way to combine these two tables into one single table?

Example data 1:

explanatory_var <- c("Urban", NA, "Married", NA, "Birth year", NA, NA, NA, NA)
levels <- c("No", "Yes", "No", "Yes", "1960", "1970", "1980", "1990", "2000")
hr <- c(NA, 0.96, NA, 0.51, NA, 1.95, 1.67, 1.46, 1.34)
low <- c(NA, 0.7, NA, 0.37, NA, 0.52, 0.52, 0.51, 0.5)
high <- c(NA, 1.32, NA, 0.71, NA, 1.77, 1.85, 2.26, 2.15)

dat <- tibble(explanatory_var, levels, hr, low, high)

data.frame(
  variable = dat$explanatory_var,
  factors = dat$levels,
  estimates = dat$hr,
  visualisation = ""
) %>%
  kable(booktabs = TRUE, linesep = "", caption = "HR", col.names = c("", "", "Estimates", "HR (95 % CI)")) %>% 
  kable_styling(latex_options = c("scale_down", "hold_position")) %>%
  column_spec(4, image = spec_pointrange(
    x = dat$hr,
    xmin = dat$low,
    xmax = dat$high,
    vline = 1)
  )

Example data 2:

explanatory_var2 <- c("Urban", NA, "Married", NA, "Birth year", NA, NA, NA, NA)
levels2 <- c("No", "Yes", "No", "Yes", "1960", "1970", "1980", "1990", "2000")
hr2 <- c(NA, 0.8, NA, 0.41, NA, 1.7, 1.5, 1.3, 1.3)
low2 <- c(NA, 0.6, NA, 0.3, NA, 0.4, 0.6, 0.5, 0.5)
high2 <- c(NA, 1.3, NA, 0.7, NA, 1.7, 1.6, 2, 2.2)

dat2 <- tibble(explanatory_var2, levels2, hr2, low2, high2)

data.frame(
  variable = dat2$explanatory_var2,
  factors = dat2$levels2,
  estimates = dat2$hr2,
  visualisation = ""
) %>%
  kable(booktabs = TRUE, linesep = "", caption = "HR", col.names = c("", "", "Estimates", "HR (95 % CI)")) %>% 
  kable_styling(latex_options = c("scale_down", "hold_position")) %>%
  column_spec(4, image = spec_pointrange(
    x = dat2$hr2,
    xmin = dat2$low2,
    xmax = dat2$high2,
    vline = 1)
  )

Solution

  • This might work:

    library(kableExtra)
    
    tab0 <- data.frame(
      variable = dat$explanatory_var,
      factors = dat$levels,
      estimates = dat$hr,
      visualisation = "")
    
    tab1 <- data.frame(
      variable = dat2$explanatory_var2,
      factors = dat2$levels2,
      estimates = dat2$hr2,
      visualisation = "")
    
    tab_merge <- cbind(tab0, tab1) # merge both
    tab_merge <- tab_merge[,c(1:4, 7:8)] # exclude duplicates
    
    tab_merge %>%
      kable(booktabs = TRUE, linesep = "", caption = "HR", col.names = c("", "", "Estimates", "HR (95 % CI)",
                                                                         "Estimates", "HR (95 % CI)")) %>% 
      kable_styling(latex_options = c("scale_down", "hold_position")) %>%
      column_spec(4, image = spec_pointrange(
        x = dat2$hr2,
        xmin = dat2$low2,
        xmax = dat2$high2,
        vline = 1)) %>%
      column_spec(6, image = spec_pointrange(
        x = dat2$hr2,
        xmin = dat2$low2,
        xmax = dat2$high2,
        vline = 1)) %>%
      add_header_above(c(" " = 2, "dat" = 2, "dat2" = 2))
    

    -output

    enter image description here