Dav*_*vid 5 r ggplot2 dplyr purrr
我有以下示例:
df <- mtcars
plot <- df %>%
mutate(carb=as.character(carb)) %>%
group_by(carb) %>%
nest() %>%
mutate(plot=map(data, function(.x){ .x %>%
ggplot() +
geom_bar(aes(mpg))
}))
print(plot)
# A tibble: 6 x 3
carb data plot
<chr> <list> <list>
1 4 <tibble [10 x 10]> <S3: gg>
2 1 <tibble [7 x 10]> <S3: gg>
3 2 <tibble [10 x 10]> <S3: gg>
4 3 <tibble [3 x 10]> <S3: gg>
5 6 <tibble [1 x 10]> <S3: gg>
6 8 <tibble [1 x 10]> <S3: gg>
for (i in 1:4){
print(plots$plot[[i]])
}
Run Code Online (Sandbox Code Playgroud)
问题:1) 如何避免 for 循环并使用 map 函数打印绘图?2)如何为情节添加标题。
制作ggplot对象的数据框列有点不寻常和麻烦,但如果适合这种情况,它可以工作。(这似乎geom_bar对这些数据实际上没有意义,所以我切换到过滤后的碳水化合物子集上的直方图)。
使用您的方法,您创建绘图列,将数据框保存到变量中,然后map2跨越绘图的列表列和carbs的向量,为每个绘图添加一个标题。然后你可以从结果列表打印任何物品,或把它们打印所有map或walk。
library(tidyverse)
df <- mtcars %>%
filter(carb %in% c(1, 2, 4)) %>%
mutate(carb = as.character(carb))
df_with_plots <- df %>%
group_by(carb) %>%
nest() %>%
mutate(plot = map(data, function(.x) {
.x %>%
ggplot() +
geom_histogram(aes(mpg))
}))
plots1 <- map2(df_with_plots$plot, df_with_plots$carb, ~(.x + labs(title = .y)))
# plots1[[1]] # would print out first plot in the list
walk(plots1, print)
Run Code Online (Sandbox Code Playgroud)

为简洁起见删除了额外的图
另一个似乎更直接的选项是将数据框拆分为数据框列表,然后根据需要为每个数据框创建图。
一些优点:调用split将 的每个值carb作为相应列表项的名称,您可以使用 轻松访问它imap,并将其保留到plots2列表中(请参阅下面我如何按名称打印绘图)。您也可以一步完成。我也很难处理嵌套数据,因为我更希望能够看到数据框,您可以通过打印出数据框的拆分列表来做到这一点。
plots2 <- df %>%
split(.$carb) %>%
imap(function(carb_df, carb) {
ggplot(carb_df) +
geom_histogram(aes(mpg)) +
labs(title = carb)
})
plots2[["4"]]
Run Code Online (Sandbox Code Playgroud)

与第一种方法一样,您可以使用walk(plots2, print).
您创建绘图的代码没有多大意义,但无论如何,您将如何在不使用 for 循环的情况下提供标题和绘制图形:
library(tidyverse)
mtcars %>%
group_split(carb) %>%
imap(~ ggplot(data = .x) +
geom_bar(aes(mpg)) +
labs(title = paste("Plot:", .y, "Carb:", unique(.x$carb))))
Run Code Online (Sandbox Code Playgroud)
由reprex 包(v0.2.1)于 2019 年 2 月 22 日创建
编辑:我删除了情节只是为了不挤满页面。在这种情况下,imap()允许我们在迭代时访问索引和值。如果您不想在标题中包含情节编号,那么map()就可以了。请注意,我还使用group_split()了最新版本的library(dplyr). 此外,在您的示例中,您创建了 ggplots 的 tibble,如果您正在执行更复杂的编码,这很好,很花哨,但在仅创建绘图的情况下,上述方法效果很好并且更容易理解。如果您想开发更复杂的图,您可以推断ggplot出map()函数并将其放入自己的函数中,如下所示:
plot_carb <- function(df){
ggplot(data = df) +
geom_bar(aes(mpg)) +
labs(title = paste(Carb: unique(.x$carb))) +
theme_bw()
}
mtcars %>%
group_split(carb) %>%
map(plot_carb)
Run Code Online (Sandbox Code Playgroud)