【问题标题】:Create the same plot for various data.frames为各种 data.frames 创建相同的图
【发布时间】:2017-09-07 21:01:35
【问题描述】:

我有三个不同的 data.frames(GRCYPT_flows、ESIEIT_flows、GRCYPT_flows),它们包含相同的变量(report_ctry、partner_ctry、indicator、year、value),但具有不同的级别/观察值。现在我想为每个 data.frames 创建图。由于图应该看起来相同,我似乎合理地使用迭代命令。我尝试了 foreach 循环:

foreach(i=GRCYPT_flows, ESIEIT_flows, GRCYPT_flows) %do% {  ggplot(i, aes(year, value)) + 
geom_line(aes(colour=partner_ctry, linetype=indicator)) + facet_wrap(~report_ctry) +
theme(axis.text.x=element_text(angle=90, vjust=0.5)) + 
scale_x_continuous(breaks=seq(2002, 2012, 2), name="") +
scale_y_continuous(name="Billion Euros") + 
scale_colour_discrete(breaks=c("EA17", "ROW_NON_EA17"), labels=c("EA17", "Extra-EA17")) +
scale_linetype_discrete(breaks=c("EA17", "ROW_NON_EA17"), labels=c("Trade", "Capital")) +
theme(legend.title=element_blank())}

该代码实际上不起作用。我在这里遇到问题:

  1. 将 data.frame 分配给迭代变量。

  2. 告诉 foreach 循环将每次迭代保存到具有不同名称(plot1、plot2、plot3 等)的不同列表中。

我比较肯定,这很容易解决,如果你对 R 有一些经验的话。但是,我是一个完全的新手,所以我真的不知道从哪里开始(我可以使用 Stata 轻松完成我至少有一些经验)。

我想做的是告诉 R:“为每个 data.frames 绘制一个图,并将每个图保存在一个单独的列表中。”

【问题讨论】:

  • 您是否有理由要使用foreach 而不是简单的for(或list+lapply)
  • 也许您可以将 data.frames 的字符名称列表传递给 foreach 并使用 get 获取实际的 data.frame。您可以使用foreach 基础架构返回一个列表(例如,参见here)。
  • @docendodiscimus 也许 OP 可以升级以在某个时候使用并行后端。
  • @docendo discimus:嗯,我愿意接受任何可行的建议。它不一定是 foreach 循环。正如我所说,我对 R 完全陌生,对许多命令一无所知。

标签: r ggplot2 foreach


【解决方案1】:

我建议将绘图代码与循环分开,这样您就可以在一个示例上对其进行测试,然后轻松地为批处理运行它。您可能希望将批处理保存到文件中。

library(tidyverse)

myplot <- function(df, filename = NULL) {
  df %>%
    ggplot(aes(Sepal.Length, Petal.Length)) +
    geom_point() ->
    result

  if(!is.null(filename)) ggsave(filename, plot = result, width = 6, height = 4)
  else result
}

# test the plot
myplot(iris)

# do the batch
l <- list(one = iris, two = iris)
l %>% names %>% walk(function(n) myplot(l[[n]], paste0(n, ".pdf")))

【讨论】:

    【解决方案2】:

    这是一个包含三个虹膜 data.frames 的示例,为简单起见,我将其命名为 i1、i2 和 i3。

    i2 <- i3 <- i1 <- iris
    
    foreach(m = 1:3) %do% {
      dat <- paste0("i" , m) %>% get
      ggplot(dat, aes(Sepal.Length, Petal.Length)) + geom_line()
    }
    

    基本上,诀窍是使用get 调用特定的data.frame。在您的情况下,这应该有效:

    data.names <- c("GRCYPT_flows", "ESIEIT_flows", "GRCYPT_flows")
    foreach(i=1:length(data.names) %do% {
      dat <- get(data.names[i])
      ggplot(dat, aes(year, value)) + 
         geom_line(aes(colour=partner_ctry, linetype=indicator)) + 
         facet_wrap(~report_ctry) +
         theme(axis.text.x=element_text(angle=90, vjust=0.5)) + 
         scale_x_continuous(breaks=seq(2002, 2012, 2), name="") +
         scale_y_continuous(name="Billion Euros") + 
         scale_colour_discrete(breaks=c("EA17", "ROW_NON_EA17"), 
         labels=c("EA17", "Extra-EA17")) +
         scale_linetype_discrete(breaks=c("EA17", "ROW_NON_EA17"), 
         labels=c("Trade", "Capital")) +
         theme(legend.title=element_blank())
      }
    

    【讨论】:

      【解决方案3】:

      我认为这里最“R”-y 的解决方案是 lapply。 Lapply 获取一个事物向量并对所有事物执行相同的操作,然后将输出存储为一个列表。由于您使用的是 ggplot,因此您可能喜欢所有相似图的整齐排列的列表。

      首先将您的数据框组织在一个列表中

      my_data  <- list(GRCYPT_flows, ESIEIT_flows) 
      

      “三个”数据框中有两个具有完全相同的名称。我将假设您实际上是指两个,但这适用于任意数量的数据帧。

      my_plots = lapply(my_data, function(i) {
      ggplot(i, aes(year, value))
      })
      

      这将获取列表中的每个元素(“i”)并对其执行自定义函数,其中自定义函数是您精心绘制的图。

      由于您使用的是 ggplot,因此您可以将这些图存储为输出。所以 my_plots 将是一个包含所有情节的整洁列表。

      所以用你的完整情节功能尝试:

          my_plot <- lapply(my_data, function(i) {
      ggplot(i, aes(year, value)) + 
      geom_line(aes(colour=partner_ctry, linetype=indicator)) + facet_wrap(~report_ctry) +
      theme(axis.text.x=element_text(angle=90, vjust=0.5)) + 
      scale_x_continuous(breaks=seq(2002, 2012, 2), name="") +
      scale_y_continuous(name="Billion Euros") + 
      scale_colour_discrete(breaks=c("EA17", "ROW_NON_EA17"), labels=c("EA17", "Extra-EA17")) +
      scale_linetype_discrete(breaks=c("EA17", "ROW_NON_EA17"), labels=c("Trade", "Capital")) +
      theme(legend.title=element_blank())
      })
      

      【讨论】:

      • 这确实有效,但它并不能完全产生我需要的东西,因为我希望 R 将每个图存储在一个单独的列表中。在这里,所有图都存储在my_plot 中。此外,当我尝试 ggsave my_plot 时,我收到错误消息 no applicable method for 'grid.draw' applied to an object of class "list"
      猜你喜欢
      • 1970-01-01
      • 2015-11-28
      • 1970-01-01
      • 1970-01-01
      • 2016-12-26
      • 1970-01-01
      • 2019-10-01
      • 2017-12-20
      相关资源
      最近更新 更多