根据连续行

时间:2017-05-29 13:31:28

标签: r loops parallel-processing

我有一组非常大的数据来自id和日期。该数据集有几亿行,大约有1000万个id。我在非Windows环境中运行,具有足够的RAM和多个处理器。我正在做这件事。目前,我正在使用multidplyr,但我正在考虑所有选项。

例如:

> df[1:11,]
          id       date gap episode
1  100000019 2015-01-24   0       1
2  100000019 2015-02-20  27       1
3  100000019 2015-03-31  39       2
4  100000019 2015-04-29  29       2
5  100000019 2015-05-27  28       2
6  100000019 2015-06-24  28       2
7  100000019 2015-07-24  30       2
8  100000019 2015-08-23  30       2
9  100000019 2015-09-21  29       2
10 100000019 2015-10-22  31       3
11 100000019 2015-12-30  69       4

数据在函数调用之前排序。订单很重要。对于每个ID,在第一个日期之后,我需要确定每个后续日期之间的天数。我称之为差距。因此,id的第一个日期得到零差距。第二个日期获取第二个日期的值减去前一行中的日期。等等。

我按ID分割数据,然后将每个id的数据发送到以下函数。

assign_gap <- function(x) {
  #  x$gap <- NA
  for(i in 1:nrow(x)) {
    x[i, ]$gap <- ifelse(i == 1, 0, x[i,]$date - x[i-1, ]$date)
  }
  return(x)
}

cluster <- create_cluster(8)
cluster_assign_value(cluster, 'assign_gap', assign_gap)
system.time(df <- df %>% partition(id, cluster = cluster) %>% do(assign_gap(.)) %>% collect())

然后我应用另一个函数,它根据allowable_gap将日期间隙的顺序分组为“剧集”(我使用的值为30)。因此,每个id可能会根据日期顺序和间隙分配多个剧集。

assign_episode <- function(x, allowable_gap){
  ep <- 1
  for(i in 1:nrow(x)){
    ifelse(x[i,]$gap <= allowable_gap, ep <- ep, ep <- ep + 1)
    x[i, ]$episode <- ep
  }
  return(x)
}

cluster <- create_cluster(8)
cluster_assign_value(cluster, 'assign_episode', assign_episode)
cluster_assign_value(cluster, 'allowable_gap', allowable_gap)
system.time(df <- df %>% partition(id, cluster = cluster) %>% do(assign_episode(., allowable_gap)) %>% collect())

鉴于我拥有的数据量,我真的想找到一种方法来避免函数中的这些循环,我希望这会大大提高效率。如果有人能想到一个完成同样事情的替代方案,我将不胜感激。

1 个答案:

答案 0 :(得分:1)

我建议使用data.table库。这个库非常快,特别是如果你正在使用像你这样的大型数据集。这是一个部分解决方案,我解决了问题的第一步:

1。在日期之间计算gap,确保每个id的第一行为0

library(data.table)

setDT(df)

df[, gap := c(0L, diff(date)) , by = id ]

即使这不是并行工作,我希望这段代码比你目前使用的循环更快。

2。当episode位于gap30

时,为连续观察分配一个组id

我还没有找到问题第二部分的解决方案,但如果他们找到解决方案,我会鼓励其他人补充这个答案。