具有分面功能的 R Pie Donut 图表

R Pie Donut chart with facet functionality

以下代码工作正常并生成所需的图表,如下所示:

library(tidyverse)
library(ggiraphExtra)

library(moonBook)

ggPieDonut(data = acs, mapping = aes(pies = Dx, donuts = smoking), interactive = TRUE)

想知道如何构建具有分面功能的圆环图。我的尝试如下:

ggPieDonut(data = acs, mapping = aes(pies = Dx, donuts = smoking), interactive = TRUE) +
  facet_wrap(facets = vars(sex))
NULL

问题

您尝试的代码不起作用,因为当 interactive = TRUEggPieDonut() 不是 return ggplot,而是 htmlwidget:

ggPieDonut(
  data = acs, 
  mapping = aes(pies = Dx, donuts = smoking), 
  interactive = TRUE
) %>% class()
#> [1] "girafe"     "htmlwidget"

并且 facet_wrap() 仅适用于 ggplots。

如果您更改为 interactive = FALSE,则会遇到另一个问题:

ggPieDonut(
  data = acs, 
  mapping = aes(pies = Dx, donuts = smoking), 
  interactive = FALSE
) + 
  facet_wrap(~sex)
#> Error in `combine_vars()`:
#> ! At least one layer must contain all faceting variables: `sex`.

geom 不包含 sex 的两个值,因此 facet_wrap() 不知道如何对其进行分面。

可能的解决方法

一个解决方案是在数据的不同子集上创建两个图,然后使用 patchwork 组合两个图:

library(patchwork)

p1 <- 
  acs %>% 
  filter(sex == "Male") %>% 
  ggPieDonut(mapping = aes(pies = Dx, donuts = smoking), interactive = FALSE) + 
  labs(title = "Male")

p2 <- 
  acs %>% 
  filter(sex == "Female") %>% 
  ggPieDonut(mapping = aes(pies = Dx, donuts = smoking), interactive = FALSE) + 
  labs(title = "Female")

p1 + p2

输出:


更新 1 - 作为一个函数

正如@MikkoMarttila 所建议的,最好将其创建为一个函数。如果我要重用这个函数,我可能会这样写:

make_faceted_plot <- function(data, pie, donut, facet_by) {
  data %>% 
    dplyr::pull( {{facet_by}} ) %>% 
    unique() %>% 
    purrr::map(
      ~ data %>% 
        dplyr::filter( {{facet_by}} == .x) %>% 
        ggiraphExtra::ggPieDonut(
          ggplot2::aes(pies = {{pie}}, donuts = {{donut}}), 
          interactive = FALSE
        ) + 
        ggplot2::labs(title = .x)
    ) %>% 
    patchwork::wrap_plots() 
}

这可以用于对我们想要的任何类别和任何数据集进行分面,例如:

library(patchwork)
library(dplyr)

# Expandable example data
df <- data.frame(
  eyes = sample(c("Blue", "Bown", "Green"), size = 100, replace = TRUE),
  hair = sample(c("blonde", "brunette", "raven"), size = 100, replace = TRUE),
  sex = sample(c("male", "female"), size = 100, replace = TRUE)
)

df %>% 
  make_faceted_plot(
    pie = eyes,
    donut = sex,
    facet_by = hair
  )

同样,正如@MikkoMarttila 所建议的,这可以通过管道传输到 ggiraph::girafe(code = print(.)) 中以增加一些交互性。


更新 2 - 更改标签

OP 希望静态和交互式图中的标签相同。

静态图和交互式图的标签都存储在 <the plot object>$plot_env 中。从这里开始,只需环顾四周,然后用交互式标签替换静态标签即可。由于交互式标签包含 HTML-tags,我们首先进行一些清理。我会把它包装在一个函数中,这样:

change_label <- function(plot) {
  
  plot$plot_env$Pielabel <- 
    plot$plot_env$data2$label %>% 
    stringr::str_replace_all("<br>", "\n") %>% 
    stringr::str_replace("\(", " \(")
  
  plot$plot_env$label2 <- 
    plot$plot_env$dat1$label %>% 
    stringr::str_replace_all("<br>", "\n") %>% 
    stringr::str_replace("\(", " \(") %>% 
    stringr::str_remove("(NSTEMI\n|STEMI\n|Unstable Angina\n)")
  
  
  plot
}

通过将此函数添加到 make_plot() 我们得到我们想要的标签:

make_faceted_plot <- function(data, pie, donut, facet_by) {
  data %>% 
    dplyr::pull( {{facet_by}} ) %>% 
    unique() %>% 
    purrr::map(
      ~ data %>% 
        dplyr::filter( {{facet_by}} == .x) %>% 
        ggiraphExtra::ggPieDonut(
          ggplot2::aes(pies = {{pie}}, donuts = {{donut}}), 
          interactive = FALSE
        ) + 
        ggplot2::labs(title = .x)
    ) %>% 
    purrr::map(change_label) %>% # <-- added change_label() here
    patchwork::wrap_plots() 
}

acs %>% 
  make_faceted_plot(
    pie = Dx,
    donut = smoking,
    facet_by = sex
  ) 

看来我和@jpiversen 的想法是一样的,所以我一开始没有 post 看到他们的答案后我的回答。但是,根据 OP 的要求,以防万一 它在某种程度上被证明是有用的,这是我的看法:


我认为简短的回答是:你不能。

函数调用中没有分面选项,结果 ggplot2 对象的数据已修改到足以无法访问 原来的专栏不再存在,使得 ggplot 之后的分面变得不可能。

但是,您可以通过构建绘图来接近分面 分别针对您想要分面的变量的每个级别,然后 将地块组合在一起。

以下是我的处理方式:

library(tidyverse)
library(ggiraphExtra)

library(moonBook)

make_plot <- function(data) {
  ggPieDonut(data = data, mapping = aes(pies = Dx, donuts = smoking))
}

plots <- by(acs, acs$sex, make_plot)
combined_plots <- patchwork::wrap_plots(plots) +
  patchwork::plot_annotation(tag_levels = list(names(plots)))

combined_plots

如果你指定interactive = TRUE,我不知道如何进行组合步骤, 但作为一种解决方法,也可以达到一些近似的交互性 对组合图进行简单的 girafe() 调用:

ggiraph::girafe(code = print(combined_plots))