有效地广播具有多个变量的大型数据集

2024-02-16

我在尝试着dcast大型数据集(数百万行)。我有一行用于到达时间和出发地,另一行用于出发时间和目的地。有一个id识别这两种情况下的单位。它看起来类似于:

id  time            movement    origin  dest
1   10/06/2011 15:54    ARR        15    15
1   10/06/2011 16:14    DEP        15    29
2   10/06/2011 17:59    ARR        73    73
2   10/06/2011 18:10    DEP        73    75
2   10/06/2011 21:10    ARR        75    75
2   10/06/2011 21:20    DEP        75    73
3   10/06/2011 17:14    ARR        17    17
3   10/06/2011 18:01    DEP        17    48
4   10/06/2011 17:14    ARR        49    49
4   10/06/2011 17:26    DEP        49    15

所以,我想重新分配这些对(ARR-DEP)并有效地做到这一点(如here https://stackoverflow.com/questions/27552810/optimizing-for-loop-in-big-data-frame)。由于它是一个非常大的数据集for loop在这种情况下不起作用。理想的输出是

  index unitid origin   arr time    dest    dep time
    1    1     15   10/06/2011 14:33    29  10/06/2011 19:24
    2    2     73   10/06/2011 14:59    75  10/06/2011 17:23
    3    2     75   10/06/2011 21:10    73  10/06/2011 23:40

Data:

        df <- structure(list(time = structure(c(7L, 16L, 8L, 11L, 18L, 20L, 
10L, 12L, 3L, 6L, 15L, 19L, 9L, 4L, 5L, 14L, 1L, 2L, 13L, 17L
), .Label = c("10/06/2011 09:08", "10/06/2011 10:54", "10/06/2011 11:38", 
"10/06/2011 12:41", "10/06/2011 12:54", "10/06/2011 14:26", "10/06/2011 14:33", 
"10/06/2011 14:59", "10/06/2011 17:12", "10/06/2011 17:14", "10/06/2011 17:23", 
"10/06/2011 18:56", "10/06/2011 19:03", "10/06/2011 19:04", "10/06/2011 19:16", 
"10/06/2011 19:24", "10/06/2011 20:12", "10/06/2011 21:10", "10/06/2011 22:28", 
"10/06/2011 23:40"), class = "factor"), movement = structure(c(1L, 
2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 3L, 1L, 2L, 2L, 1L, 
2L, 2L, 3L), .Label = c("ARR", "DEP", "ITZ"), class = "factor"), 
    origin = c(15L, 15L, 73L, 73L, 75L, 75L, 17L, 17L, 49L, 49L, 
    15L, 15L, 32L, 10L, 10L, 17L, 76L, 76L, 76L, 76L), dest = c(15L, 
    29L, 73L, 75L, 75L, 73L, 17L, 48L, 49L, 15L, 15L, 49L, 32L, 
    10L, 17L, 10L, 76L, 65L, 76L, 65L), id = c(1L, 1L, 2L, 2L, 
    2L, 2L, 3L, 3L, 4L, 4L, 4L, 4L, 5L, 6L, 6L, 6L, 7L, 7L, 8L, 
    8L)), .Names = c("time", "movement", "origin", "dest", "id"
), row.names = c(NA, -20L), class = "data.frame")

这个怎么样?使用data.table:

require(data.table)
setorder(setDT(df), id, time)
df[, grp := FALSE][movement == "ARR", grp := TRUE]
df[, .(time[grp], time[!grp], origin[grp], dest[!grp]), by=id]
#    id                  V1                  V2 V3 V4
# 1:  1 10/06/2011 14:33:57 10/06/2011 19:24:16 15 29
# 2:  2 10/06/2011 14:59:14 10/06/2011 17:23:20 73 75
# 3:  2 10/06/2011 21:10:56 10/06/2011 23:40:29 75 73
# 4:  3 10/06/2011 17:14:44 10/06/2011 18:56:39 17 48
# 5:  4 10/06/2011 11:38:43 10/06/2011 14:26:43 49 15
# 6:  4 10/06/2011 19:16:55 10/06/2011 22:28:14 15 49
# 7:  5 10/06/2011 10:41:20 10/06/2011 12:54:26 10 17
# 8:  6 10/06/2011 09:08:05 10/06/2011 10:54:48 76 65

如果您添加另一列具有值的列,则可以稍微加快速度!grp并使用该列而不是做!grp在每个组上。


这是如何运作的:

  • setDT通过引用将 data.frame 转换为 data.table。

  • setorder根据提供的列(和顺序)通过引用对 data.table 重新排序。在这里,它重新排序了行df根据列按升序排列id and time.

  • 然后我们使用data.table的通过引用进行子分配添加一个额外的列来保存该值TRUE when movement == "ARR" and FALSE when movement == "DEP".

    注意:您的因子水平df$movement列有一个附加级别,称为ITZ这似乎并不在此示例数据中。不知道如何处理。

  • 现在我们要做的就是从其中选择 1,3,5,.. 元素origin和 2,4,6,... 元素来自dest(同样对于time).

只要这样就有效ARR时间总是在之前DEP时间(这是一个非常有效的假设)。


根据OP对Q的编辑,数据不一致:

na.omit(df[movement != "ITZ", .(time[grp], time[!grp], origin[grp], dest[!grp]), by=id])
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有效地广播具有多个变量的大型数据集 的相关文章

随机推荐