【问题标题】:arrange multiple graphs using a for loop in ggplot2在ggplot2中使用for循环排列多个图形
【发布时间】:2014-04-23 06:15:15
【问题描述】:

我想制作一个显示多个图表的 pdf,每个图表对应一个 NetworkTrackingPixelId。 我有一个类似这样的数据框:

> head(data)
  NetworkTrackingPixelId                           Name       Date Impressions
1                   2421                    Rubicon RTB 2014-02-16      168801
2                   2615                     Google RTB 2014-02-16     1215235
3                   3366                      OpenX RTB 2014-02-16      104419
4                   3606                   AppNexus RTB 2014-02-16      170757
5                   3947                   Pubmatic RTB 2014-02-16       68690
6                   4299            Improve Digital RTB 2014-02-16         701

我正在考虑使用类似于下面的脚本:

# create a vector which stores the NetworkTrackingPixelIds
tp <- data %.%
        group_by(NetworkTrackingPixelId) %.%
        select(NetworkTrackingPixelId)

# create a for loop to print the line graphs
for (i in tp) {
      print(ggplot(data[which(data$NetworkTrackingPixelId == i), ], aes(x = Date, y = Impressions)) + geom_point() + geom_line())
    }

我希望这个命令能够生成许多图表,每个 NetworkTrackingPixelId 一个。相反,结果是一个聚合所有 NetworkTrackingPixelIds 的唯一图表。

我注意到的另一件事是变量tp 不是真正的向量。

> is.vector(tp)
[1] FALSE

即使我强迫它..

tp <- as.vector(data %.%
        group_by(NetworkTrackingPixelId) %.%
        select(NetworkTrackingPixelId))
> is.vector(tp)
[1] FALSE
> str(tp)
Classes ‘grouped_df’, ‘tbl_df’, ‘tbl’ and 'data.frame': 1397 obs. of  1 variable:
 $ NetworkTrackingPixelId: int  2421 2615 3366 3606 3947 4299 4429 4786 6046 6286 ...
 - attr(*, "vars")=List of 1
  ..$ : symbol NetworkTrackingPixelId
 - attr(*, "drop")= logi TRUE
 - attr(*, "indices")=List of 63
  ..$ : int  24 69 116 162 205 253 302 351 402 454 ...
  ..$ : int  1 48 94 140 184 232 281 330 380 432 ...

[I've cut a bit this output]

 - attr(*, "group_sizes")= int  29 29 2 16 29 1 29 29 29 29 ...
 - attr(*, "biggest_group_size")= int 29
 - attr(*, "labels")='data.frame':  63 obs. of  1 variable:
  ..$ NetworkTrackingPixelId: int  8799 2615 8854 8869 4786 7007 3947 9109 9126 9137 ...
  ..- attr(*, "vars")=List of 1
  .. ..$ : symbol NetworkTrackingPixelId

【问题讨论】:

  • 不知道你的问题是不是用 facetting 解决不了?

标签: r for-loop ggplot2


【解决方案1】:

我认为您最好编写一个绘图函数,然后对每个网络跟踪像素使用 lapply。

例如,您的函数可能如下所示:

plot.function <- function(ntpid){
  sub = subset(dataset, dataset$networktrackingpixelid == ntpid)
  ggobj = ggplot(data=sub, aes(...)) + geom...
  ggsave(filename=sprintf("%s.pdf", ntpid))
}

举一个可重现的例子会对你有所帮助,但我希望这能奏效!虽然不确定矢量问题..

干杯!

【讨论】:

    【解决方案2】:

    除非我遗漏了什么,否则通过子集变量生成图非常简单。您可以使用split(...) 将原始数据拆分为NetworkTrackingPixelId 的数据框列表,然后使用lapply(...) 将它们传递给ggplot。下面的大部分代码只是为了创建一个示例数据集。

    # create sample data
    set.seed(1)
    names <- c("Rubicon","Google","OpenX","AppNexus","Pubmatic")
    dates <- as.Date("2014-02-16")+1:10
    df <- data.frame(NetworkTrackingPixelId=rep(1:5,each=10),
                     Name=sample(names,50,replace=T),
                     Date=dates,
                     Impressions=sample(1000:10000,50))
    # end create sample data
    
    pdf("plots.pdf")
    lapply(split(df,df$NetworkTrackingPixelId),
           function(gg) ggplot(gg,aes(x = Date, y = Impressions)) + 
              geom_point() + geom_line()+
              ggtitle(paste("NetworkTrackingPixelId:",gg$NetworkTrackingPixelId)))
    dev.off()
    

    这会生成一个包含 5 个绘图的 pdf,每个绘图对应一个 NetworkTrackingPixelId

    【讨论】:

      【解决方案3】:

      我最近有一个项目,需要为每条记录生成大量单独的 png。我发现我在做一些非常简单的并行化时得到了极大的加速。我不确定这是否比dplyrdata.table 技术更高效,但它可能值得一试。我看到了一个巨大的减速带:

      require(foreach)
      require(doParallel)
      workers <- makeCluster(4)
      registerDoParallel(workers) 
      foreach(i = seq(1, length(mtcars$gear)), .packages=c('ggplot2')) %dopar% {
        j <- qplot(wt, mpg, data = mtcars[i,])
        png(file=paste(getwd(), '/images/',mtcars[i, c('gear')],'.png', sep=''))
        print(j)
        dev.off()
      }
      

      【讨论】:

        【解决方案4】:

        由于我没有您的数据集,我将使用mtcars 数据集来说明如何使用dplyrdata.table 执行此操作。这两个包都是 rstats 中 split-apply-combine 范式的最佳示例。让我解释一下:

        第 1 步按齿轮拆分数据

        • dplyr 使用函数group_by
        • data.table 使用参数 by

        第 2 步:应用函数

        • dplyr 使用 do,您可以将使用片段 x 的函数传递给它。
        • data.table 在每个片段的上下文中将变量解释为函数。

        第 3 步:合并

        这里没有合并步骤,因为我们将创建的图表保存到文件中。

        library(dplyr)
        mtcars %.%
          group_by(gear) %.%
          do(function(x){ggsave(
            filename = sprintf("gear_%s.pdf", unique(x$gear)), qplot(wt, mpg, data = x)
          )})
        
        library(data.table)
        mtcars_dt = data.table(mtcars)
        mtcars_dt[,ggsave(
          filename = sprintf("gear_%s.pdf", unique(gear)), qplot(wt, mpg)),
          by = gear
        ]
        

        更新:要将所有文件保存到一个 pdf 中,这里有一个快速解决方案。

        plots = mtcars %.%
          group_by(gear) %.%
          do(function(x) {
            qplot(wt, mpg, data = x)
          })
        
        pdf('all.pdf')
        invisible(lapply(plots, print))
        dev.off()
        

        【讨论】:

        • 感谢拉姆纳特!那真的很有用。我正在尝试将所有图形保存在一个唯一的 .pdf 文件中。我尝试使用以下函数: data %.% group_by(NetworkTrackingPixelId) %.% do(function(x) { pdf(file = "C:\\Users\\gianluca.rossi\\Dropbox\\Data Analysis \\figure.pdf") ggplot(x, aes(x = Date, y = Impressions)) + geom_point() + geom_line() dev.off() } ) 但不幸的是它返回一个空的 .pdf 文件。
        • 那行不通。请参阅我更新的解决方案。问题是在do 循环中,您仍然只处理一个数据。
        • 绝对喜欢这个答案。但是,如果我想使用例如安排我的情节怎么办?安排格罗布。 mult_plot
        • print(do.call(arrangeGrob, plots)).
        • dplyr 示例当前异常终止抱怨Results 1, 2, 3, 4, 5, ... must be data frames, not function。我相信您需要将函数包装如下(function(x){&lt;code-here&gt;})(.)。希望对某人有所帮助
        猜你喜欢
        • 1970-01-01
        • 2021-09-23
        • 1970-01-01
        • 1970-01-01
        • 2018-01-27
        • 2021-10-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多