rggplot2dplyrpurrrgt

Plot histograms per row using gt tables - R


I want to create a gt table where I see some metrics like number of observations, mean and median, and I want a column with its histogram. For this question I will use the iris dataset.

I have recently learned how to put a plot in a tibble using this code:

library(dplyr)
library(tidyr)
library(purrr)
library(gt)
my_tibble <- iris %>%
  pivot_longer(-Species, 
               names_to = "Vars", 
               values_to = "Values") %>%
  group_by(Vars) %>%
  summarise(obs = n(),
            mean = round(mean(Values),2),
            median = round(median(Values),2), 
            plots = list(ggplot(cur_data(), aes(Values)) + geom_histogram()))

Now I want to use the plots column for plotting an histogram per variable, so I have tried this:

my_tibble %>%
  mutate(ggplot = NA) %>%
  gt() %>%
  text_transform(
    locations = cells_body(vars(ggplot)),
    fn = function(x) {
      map(.$plots,ggplot_image)
    }
  )

But it returns me an error:

Error in body[[col]][stub_df$rownum_i %in% loc$rows] <- fn(body[[col]][stub_df$rownum_i %in%  : 
  replacement has length zero

The gt table should be like this: enter image description here

Any help will be greatly appreciated.


Solution

  • We need to loop over the plots

    library(dplyr)
    library(tidyr)
    library(purrr)
    library(gt)
    library(ggplot2)
    iris %>%
      pivot_longer(-Species, 
                   names_to = "Vars", 
                   values_to = "Values") %>%
      nest_by(Vars) %>%
      mutate(n = nrow(data),
             mean = round(mean(data$Values), 2), 
             median = round(median(data$Values), 2), 
             plots = list(ggplot(data, aes(Values)) + geom_histogram()), .keep = "unused") %>%
      ungroup %>%
      mutate(ggplot = NA) %>%
      {dat <- .
      dat %>%
        select(-plots) %>%
        gt() %>%
      text_transform(locations = cells_body(c(ggplot)),
                     fn = function(x) {
                      map(dat$plots, ggplot_image, height = px(100))
                     }
                     
                     
                     )
      }
    

    -check for the output enter image description here