在data.table中使用带有多个变量的超前/滞后

时间:2018-01-22 11:26:04

标签: r dplyr data.table

我的目标是使用data.table计算离开电台的自行车数量,然后按station_idhourdate进行汇总。< / p>

如果之前的记录 - bikes_available的当前记录是正数,那么这就是自行车丢失的数量。如果前一记录 - 当前记录为负或零,则表示自行车数量保持不变或增加,因此不应计算这些情况。

> head(dat, n = 10)
    station_id bikes_available                time       date hour
 1:          3               2 2018-01-15 01:58:02 2018-01-15    1
 2:          3               1 2018-01-15 01:59:01 2018-01-15    1
 3:          3               1 2018-01-15 02:00:03 2018-01-15    2
 4:          3               4 2018-01-15 02:01:02 2018-01-15    2
 5:          3               4 2018-01-15 02:02:02 2018-01-15    2
 6:          3               1 2018-01-15 02:03:02 2018-01-15    2
 7:          3               1 2018-01-15 02:04:02 2018-01-15    2
 8:          3               1 2018-01-15 02:05:02 2018-01-15    2
 9:          3               7 2018-01-15 02:06:02 2018-01-15    2
10:          3               3 2018-01-15 02:07:02 2018-01-15    2

lead函数可用于查找先前记录和当前记录之间的差异,然后仅使用以下过滤掉的正值:

dat[,ba_lead:=shift(bikes_available, 1, type='lead')]
dat$diff <- dat$bikes_available - dat$ba_lead

但是如何使用station_id将3个变量 - time datedata.table分组?

例如,可以从提供的数据中获得以下输出

> output
  station_id bikes_taken hour       date
1          3           1    1 2018-01-15
2          3           7    2 2018-01-15
3          4           4    1 2018-01-15
4          4           1    2 2018-01-15
5          5           0    1 2018-01-15
6          5           2    2 2018-01-15

(下面的完整数据集)

> dput(dat)
structure(list(station_id = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 
5L, 5L, 5L, 5L, 5L, 5L), bikes_available = c(2, 1, 1, 4, 4, 1, 
1, 1, 7, 3, 4, 0, 0, 0, 0, 0, 1, 1, 1, 0, 5, 5, 5, 5, 4, 4, 4, 
4, 3, 3), time = structure(c(1516010282, 1516010341, 1516010403, 
1516010462, 1516010522, 1516010582, 1516010642, 1516010702, 1516010762, 
1516010822, 1516010282, 1516010341, 1516010403, 1516010462, 1516010522, 
1516010582, 1516010642, 1516010702, 1516010762, 1516010822, 1516010282, 
1516010341, 1516010403, 1516010462, 1516010522, 1516010582, 1516010642, 
1516010702, 1516010762, 1516010822), class = c("POSIXct", "POSIXt"
), tzone = ""), date = structure(c(17546, 17546, 17546, 17546, 
17546, 17546, 17546, 17546, 17546, 17546, 17546, 17546, 17546, 
17546, 17546, 17546, 17546, 17546, 17546, 17546, 17546, 17546, 
17546, 17546, 17546, 17546, 17546, 17546, 17546, 17546), class = "Date"), 
    hour = c(1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L)), .Names = c("station_id", "bikes_available", 
"time", "date", "hour"), row.names = c(NA, -30L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x102800778>)

3 个答案:

答案 0 :(得分:1)

使用tidyverse函数,您可以尝试:

df %>%
  group_by(station_id, date, hour) %>%
  mutate( b_taken = bikes_available - lead(bikes_available)) %>%
  filter(b_taken >= 0) %>%
  mutate(b_taken = sum(b_taken)) %>%
  select(b_taken) %>%
  unique()

给出:

  station_id       date  hour b_taken
       <int>     <date> <int>   <dbl>
1          3 2018-01-15     1       1
2          3 2018-01-15     2       7
3          4 2018-01-15     1       4
4          4 2018-01-15     2       1
5          5 2018-01-15     1       0
6          5 2018-01-15     2       2

答案 1 :(得分:1)

library("data.table")
setDT(dat)
dat[, 
    j = .(bikes_taken = bikes_available - shift( x = bikes_available, n = 1, type = 'lead')),
    by = .(station_id, date, hour)][ i = bikes_taken >= 0, 
                                     j = .(bikes_taken = sum(bikes_taken)), 
                                     by = .(station_id, date, hour)]

#    station_id       date hour bikes_taken
# 1:          3 2018-01-15    1           1
# 2:          3 2018-01-15    2           7
# 3:          4 2018-01-15    1           4
# 4:          4 2018-01-15    2           1
# 5:          5 2018-01-15    1           0
# 6:          5 2018-01-15    2           2

答案 2 :(得分:1)

data.table的另一种看法:

dat[, .(bikes_taken = diff(bikes_available)), by = .(station_id, date, hour)
    ][bikes_taken <= 0, .(bikes_taken = sum(bikes_taken*-1)), by = .(station_id, date, hour)]

给出:

   station_id       date hour bikes_taken
1:          3 2018-01-15    1           1
2:          3 2018-01-15    2           7
3:          4 2018-01-15    1           4
4:          4 2018-01-15    2           1
5:          5 2018-01-15    1           0
6:          5 2018-01-15    2           2