具有分面功能的 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 = TRUE
、ggPieDonut()
不是 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))
以下代码工作正常并生成所需的图表,如下所示:
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 = TRUE
、ggPieDonut()
不是 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))