使用ggplot2中的for循环排列多个图形

时间:2014-03-17 20:23:26

标签: r for-loop ggplot2

我想制作一个显示多个图表的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

4 个答案:

答案 0 :(得分:12)

由于我没有您的数据集,因此我将使用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()

答案 1 :(得分:1)

我最近有一个项目需要为每条记录生成大量的个人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()
}

答案 2 :(得分:0)

我认为你最好编写一个绘图功能,然后在每个网络跟踪像素上使用lapply。

例如,您的功能可能如下所示:

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

您可以使用可重复的示例,但我希望这有效!虽然不确定矢量问题..

干杯!

答案 3 :(得分:0)

除非我遗漏了某些内容,否则通过子集化变量生成绘图非常简单。您可以使用split(...)将原始数据拆分为NetworkTrackingPixelId的数据框列表,然后使用ggplot将其传递给lapply(...)。下面的大多数代码只是为了创建一个样本数据集。

# 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一个。