flextable:嵌入 ggpplots 使用来自 2 列的数据和列表(用于比较)作为每行的单个图

flextable: embed ggpplots using data from 2 columns with lists (for comparing) as a single plot per row

关注https://ardata-fr.github.io/flextable-book/cell-content-1.html#base-plots-and-ggplot-objects我想要小地块

   gg_line <- function(z) {
  z <- scale(z)
  z <- na.omit(z)
  z <- data.frame(x = seq_along(z), z = z)
  ggplot(z, aes(x = x, y = z)) +
    geom_line(show.legend = FALSE) +
    theme_void()
}

构建数据集,嵌入数据列表。

  dat <- as.data.table(mtcars)
z <- dat[,
         lapply(.SD, function(x) list(gg_line(x))),
         by = c("vs", "am"), .SDcols = c("mpg", "disp")
]

用绘图替换单元格中的 ggplot 数据。

  ft <- flextable(z)
ft <- compose(ft, 
              j = c("mpg", "disp", "drat"),
              value = as_paragraph(gg_chunk(value = ., height = .15, width = 1)),
              use_dot = TRUE
)
ft

结果我有 2 列带图。

我想知道如何更改代码,以便生成一列而不是两列:每行一个 ggplot,叠加两个 geom(在本例中为“mpg”和“disp”,但这可能是 数据集中存在的两个组 就像两个公司,两个物种)。我希望我可以在每个单元格中并排绘制 两个箱形图或在一个单元格中绘制两个小提琴图 。有没有一种简单的方法可以将来自两列的两个列表组合起来,以生成一列,每条记录都有一个图,显示来自两个列表(两层)的数据?

不幸的是,我缺乏通过 data.table 进行数据整理的 data.table 技能,但使用 tidyverse 可以像这样实现:

library(flextable)
library(ggplot2)
library(tidyr)
library(dplyr)

gg <- function(z, cols, type = "box") {
  z <- z[, cols]
  z <- dplyr::mutate(z, dplyr::across(all_of(cols), scale), x = seq(nrow(z)))
  z <- na.omit(z)
  z <- tidyr::pivot_longer(z, -x)
  
  geom <- switch(type,
                 line = geom_line(aes(x = x), show.legend = FALSE),
                 box = geom_boxplot(aes(x = name), show.legend = FALSE, size = .1))
  ggplot(z, aes(y = value, color = name)) +
    geom +
    theme_void()
}

dat <- mtcars
dat <- dat %>% 
  tidyr::nest(data = -c(vs, am)) %>% 
  dplyr::mutate(
    line = lapply(data, function(x) gg(x, cols = c("mpg", "disp"), "line")),
    box = lapply(data, function(x) gg(x, cols = c("mpg", "disp"), "box"))) %>% 
  dplyr::select(-data)

ft <- flextable(dat[, c("vs", "am", "line")])
ft <- compose(ft, 
              j = c("line"),
              value = as_paragraph(gg_chunk(value = ., height = .15, width = 1)),
              use_dot = TRUE
)
ft

ft <- flextable(dat[, c("vs", "am", "box")])
ft <- compose(ft, 
              j = c("box"),
              value = as_paragraph(gg_chunk(value = ., height = .15, width = 1)),
              use_dot = TRUE
)
ft