1

I would like to use the functionality of modelsummary::datasummary_skim such that two tables are aligned side-by-side including the histograms and only the mean of the variables, e.g.

library(modelsummary)
library(dplyr)
library(kableExtra)

normal_df <- data.frame(
  var1 = c(1:3, 50:53, 100:102),
  var2 = runif(10),
  var3 = seq(10, 100, 10)
)


outlier_df <- tibble::tribble(
  ~var1, ~var2, ~var3,
  1, 1000, 10.5,
  2, 20000, 100.6,
  3, 32, 1000.3
) %>% as.data.frame()

# This is how datasummary_skim looks like
datasummary_skim(normal_df)

# this is how it could work using datasummary
datasummary(All(normal_df) ~ Mean + Histogram, normal_df) %>%
  kable_styling(full_width = FALSE, position = "float_left") %>%
  add_header_above(c("", "Normal" = 2))
datasummary(All(outlier_df) ~ Mean + Histogram, outlier_df) %>%
  kable_styling(full_width = FALSE, position = "left") %>%
  add_header_above(c("", "Outlier" = 2))

The problem is that the histograms are not displayed anymore. Any ideas/hints are much appreciated!

Julian
  • 6,586
  • 2
  • 9
  • 33

2 Answers2

1

EDIT: As pointed out in the comments below, this may not work on all operating systems (Works on Debian 11)

One way to solve this is to combine all the data in a single data frame, then use the nesting feature in datasummary -

normal_df$type <- "normal"
outlier_df$type <- "outlier"
all_df <- rbind(normal_df,outlier_df)
datasummary(All(all_df) ~ (Mean + Histogram) * type,
            data = all_df)

Output

akshaymoorthy
  • 326
  • 1
  • 4
  • 2
    Thanks for the answer. Please note that these histograms may not display well on every operating system or with every font. The docs have an example using SVG histograms using the `kableExtra` package which, I think, are safer to use: https://vincentarelbundock.github.io/modelsummary/articles/datasummary.html#histograms – Vincent Aug 11 '22 at 12:06
  • 1
    Your solution works in general, but on Windows I cannot see the histograms :( – Julian Aug 11 '22 at 13:50
  • 2
    Thank you for pointing this out, edited my answer to indicate my OS as well. – akshaymoorthy Aug 11 '22 at 14:21
  • @Vincent I tried that one, however, the histogram is quite small. When I adjust that using the `width` and `height` arguments inside `spec_hist()` the alignment does not work anymore. Any ideas what I could do? – Julian Aug 11 '22 at 15:06
  • 1
    What do you mean exactly by "alignment does not work"? Did you try the `same_lim` argument? – Vincent Aug 11 '22 at 15:29
  • 1
    Sometimes the solution is directly in front of you, thank you Vincent :) great package btw – Julian Aug 12 '22 at 08:43
1

I solved my problem thanks to @Vincent.

tmp_list <- lapply(normal_df, na.omit)
tmp_list <- lapply(tmp_list, scale)

tmp_list2 <- lapply(outlier_df, na.omit)
tmp_list2 <- lapply(tmp_list2, scale)


emptycol = function(x) " "


kbl1 <- datasummary(All(normal_df) ~ Mean + SD + Heading("Boxplot") * emptycol + Heading("Histogram") * emptycol, data = normal_df) %>%
  column_spec(column = 4, image = spec_boxplot(tmp_list, same_lim = FALSE)) %>%
  column_spec(column = 5, image = spec_hist(tmp_list, same_lim = FALSE)) %>%
  kable_styling(full_width = FALSE, position = "float_left", font_size = 12) %>%
  add_header_above(c("", "Normal" = 4))

kbl2 <- datasummary(All(outlier_df) ~ Mean + SD + Heading("Boxplot") * emptycol +
                      Heading("Histogram") * emptycol, data = outlier_df) %>%
  column_spec(column = 4, image = spec_boxplot(tmp_list2, same_lim = FALSE)) %>%
  column_spec(column = 5, image = spec_hist(tmp_list2, same_lim = FALSE)) %>%
  kable_styling(full_width = FALSE, position = "left", font_size = 12) %>%
  add_header_above(c("", "Outlier" = 4))

knitr::kables(list(kbl1,kbl2)) %>% kable_styling()
Julian
  • 6,586
  • 2
  • 9
  • 33