【问题标题】:Using dplyr/ggplot2 inside for loops在 for 循环中使用 dplyr/ggplot2
【发布时间】:2016-12-08 08:58:20
【问题描述】:

我正在尝试根据存储在向量中的列中的 11 个不同级别过滤和绘制 11 个不同的图表。

对于一个快速的、可重现的示例,这基本上是我尝试过的:

library(dplyr)
library(ggplot)
positions = c("forward", "defense")

df <- data.frame(player = c("Sergio Ramos", "Lionel Messi",
                            "Dani Alvez", "Christiano Ronaldo"),
                 position = c("forward", "defense", "defense", "forward"),
                 goals = c(12, 8, 2, 23))

for (i in 1:length(positions)) {
  df %>%
    filter(position == positions[i]) %>%
    print(ggplot(aes(x = player, y = goals)) +
      geom_bar(stat = "identity"))
}

如果我只是将过滤器包装在 print() 中并运行它,我会得到两个子集:

             player position goals
1       Sergio Ramos  forward    12
2 Christiano Ronaldo  forward    23
        player position goals
1 Lionel Messi  defense     8
2   Dani Alvez  defense     2

但是上面的代码给了我

错误:ggplot2 不知道如何处理 uneval 类的数据。

如果我在没有循环的情况下运行代码,它的图形效果很好。

我希望能够遍历变量并将它们全部发布到 Rmd 中或全部保存。有人可以解释为什么上述方法不起作用吗?谢谢!

【问题讨论】:

  • 这个ggplot(df, aes(x = player, y = goals)) + geom_bar(stat = 'identity') +facet_wrap(~position) ?

标签: r loops ggplot2 dplyr


【解决方案1】:

使用 dplyr 管道会将数据帧放在错误的位置。试试这样吧:

library(dplyr)
library(ggplot2)
positions = c("forward", "defense")

df <- data.frame(player = c("Sergio Ramos", "Lionel Messi",
                            "Dani Alvez", "Christiano Ronaldo"),
                 position = c("forward", "defense", "defense", "forward"),
                 goals = c(12, 8, 2, 23))

for (i in 1:length(positions)) {
  df %>%
    filter(position == positions[i]) %>%
    ggplot(aes(x = player, y = goals)) +
            geom_bar(stat = "identity") -> g
    print(g)
}

你也可以考虑用 lapply 重写循环。

【讨论】:

  • 为什么要在调用结束时分配ggplot2对象?
  • 如果我这样堆叠它 df %&gt;% filter(position == positions[i]) %&gt;% gplot(aes(x = player, y = goals)) + geom_bar(stat = "identity") %&gt;% print() ,它只会打印关于几何图形的文本信息。
  • 更多语法问题。我认为典型的 R 约定是在左侧分配对象,所以我只是想知道这是一个例外还是有什么目的。
  • 我发现使用 %&gt;% 流水线时更容易理解,但我同意,左手分配更传统。
  • 我认为这个解决方案最适合我目前的需求。我尝试使用 facet_wrap(),但如果你有多个值和多个 x 值,它似乎并没有那么好。
【解决方案2】:

你真的不需要任何类型的循环来获得你需要的东西。 facet_wrap 可以满足您的需求。即

ggplot(df, aes(x = player, y = goals)) + geom_bar(stat = 'identity') +facet_wrap(~position)

【讨论】:

  • 当您的数据较大时(即您的 x 值超过 4 个),x 变得不可读(名称重叠严重)。有没有办法解决这个问题?
  • 您可以在名称上使用make.unique() 以避免重叠
【解决方案3】:

如果你想把所有的地块独立地放在一个地方(不使用 facet_wrap),你可以尝试以下方法:

  • 将数据框分成由位置定义的组。

    dfx &lt;- split(df,as.factor(df$position))

lapply 解决方案

您还可以在拆分的数据帧上使用 lapply,如下所示:

  • 定义一个产生你想要的情节的函数

    my_plot <- function(x){ g <- ggplot(x,aes(x = player, y = goals)) + geom_bar(stat = "identity") }

  • 使用 lapply

ggy &lt;- lapply(dfx,my_plot)

您将拥有 ggy 中的所有地块:

ggy$defense
ggy$forward

for循环解决方案

  • 创建一个空列表以保留所有绘图。

    ggx &lt;- list()

  • 循环并将每个图保存在 ggx 列表中。

    for(i in 1:length(positions)){
        # create a barplot and save in g
        g <- ggplot(dfx[[i]],aes(x = player, y = goals)) +
                geom_bar(stat = "identity")
    
        n <- dfx[[i]]$position %>% unique() %>% as.character()
    
        # add the plot to the list
        ggx[[n]] <- g
    

    }

现在你的地块在:

ggx[[1]] or ggx$defense
ggx[[2]] or ggx$forward

您可以随时随地打印、保存或获取信息。

> ggx$defense$data
        player position goals
2 Lionel Messi  defense     8
3   Dani Alvez  defense     2

【讨论】:

  • 可能是最完整的答案
【解决方案4】:

下面将在您的工作目录中的 pdf 的每一页中保存一个绘图

pdf("out.pdf", width = 7, height = 7)
for (i in 1:length(positions)) {
 print( df %>%
    filter(position == positions[i]) %>%
  ggplot(aes(x = player, y = goals)) +
            geom_bar(stat = "identity"))
}
dev.off() 

对于以 the markdown cheat sheet here 开头的降价文档。

但是我认为您可能想考虑使用 facet_gridfacet_wrap 函数并以与上述相同的方法将其保存为 pdf

【讨论】:

    【解决方案5】:

    你也可以这样做:

    for (i in positions) {
      dfplt <- df %>%
        filter(position == positions) 
        plt <- ggplot(dfplt,aes(x = player, y = goals)) +
                geom_bar(stat = "identity")
        ggsave(plt, file=paste0(i,"_plot.png"))
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-19
      • 1970-01-01
      • 2021-08-05
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      • 2020-11-23
      • 2016-10-15
      相关资源
      最近更新 更多