引用前导行

时间:2017-09-27 02:43:25

标签: r dplyr data.table plyr

我有一个样本数据集,可以跟踪不同车站的自行车轨迹。我的目标是找到自行车在difftime()的特定车站保留的间隔,在本例中为B站。

> test
   bikeid start_station           starttime end_station             endtime
1       1             A 2017-09-25 01:00:00           B 2017-09-25 01:30:00
2       1             B 2017-09-25 07:30:00           C 2017-09-25 08:00:00
3       1             C 2017-09-25 10:00:00           A 2017-09-25 10:30:00
4       1             A 2017-09-25 13:00:00           C 2017-09-25 13:30:00
5       1             C 2017-09-25 15:30:00           B 2017-09-25 16:00:00
6       1             B 2017-09-25 18:00:00           B 2017-09-25 18:30:00
7       1             B 2017-09-25 19:00:00           A 2017-09-25 19:30:00
8       1             А 2017-09-25 20:00:00           B 2017-09-25 20:30:00
9       1             C 2017-09-25 22:00:00           C 2017-09-25 22:30:00
10      1             B 2017-09-25 23:00:00           C 2017-09-25 23:30:00 

有时,自行车不会在他们结束的同一站点开始,这些情况应该被忽略。在上面的数据集中,我们可以看到在01:30:0007:30:00之间经过了360分钟,在16:00:0018:00:00之间经过了120分钟,而在{18:30:00之间经过了30分钟1}}和19:00:00。第8行和第10行被忽略,因为自行车不会在它结束的同一站点启动。因此,输出向量应为:

[1] 360 120  30

以下代码使用不会产生所需的输出:

sapply(test$starttime[test$end_station == "B"], function(x, et) difftime(et[x < et][1], x, units = "mins"), et = test$endtime[test$start_station == "B"])

只有当下一行中的difftime()end_station相等时,如何考虑下一行并计算start_station?在lead()中使用dplyr?任何建议将不胜感激

以下是示例数据:

> dput(test)
structure(list(bikeid = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), start_station = c("A", 
"B", "C", "A", "C", "B", "B", "А", "C", "B"), starttime = structure(c(1506315600, 
1506339000, 1506348000, 1506358800, 1506367800, 1506376800, 1506380400, 
1506384000, 1506391200, 1506394800), class = c("POSIXct", "POSIXt"
), tzone = ""), end_station = c("B", "C", "A", "C", "B", "B", 
"A", "B", "C", "C"), endtime = structure(c(1506317400, 1506340800, 
1506349800, 1506360600, 1506369600, 1506378600, 1506382200, 1506385800, 
1506393000, 1506396600), class = c("POSIXct", "POSIXt"), tzone = "")), .Names = c("bikeid", 
"start_station", "starttime", "end_station", "endtime"), row.names = c(NA, 
-10L), class = "data.frame")

2 个答案:

答案 0 :(得分:5)

上次重新塑造as suggested ......

library(data.table)

mtest = melt(setDT(test), id="bikeid", 
  meas = patterns("_station", "time"), 
  variable.name = "event", 
  value.name = c("station", "time"))
mtest[.(factor(1:2), c("start", "end")), on=.(event), event := i.V2]
setkey(mtest, bikeid, time)

然后在自行车闲置的时候回到广阔的地方......

idleDT = dcast(mtest[-c(1,.N)][, g := rep(1:.N, each=2, length.out=.N)], 
  g ~ rowid(g), value.var=c("station", "time"))

   g station_1 station_2              time_1              time_2
1: 1         B         B 2017-09-25 01:30:00 2017-09-25 07:30:00
2: 2         C         C 2017-09-25 08:00:00 2017-09-25 10:00:00
3: 3         A         A 2017-09-25 10:30:00 2017-09-25 13:00:00
4: 4         C         C 2017-09-25 13:30:00 2017-09-25 15:30:00
5: 5         B         B 2017-09-25 16:00:00 2017-09-25 18:00:00
6: 6         B         B 2017-09-25 18:30:00 2017-09-25 19:00:00
7: 7         A  <U+0410> 2017-09-25 19:30:00 2017-09-25 20:00:00
8: 8         B         C 2017-09-25 20:30:00 2017-09-25 22:00:00
9: 9         C         B 2017-09-25 22:30:00 2017-09-25 23:00:00

然后加入或过滤并计算......

idleDT[.("B", "B"), on=.(station_1, station_2), time_2 - time_1 ]

Time differences in mins
[1] 360 120  30

注释

我应该解释为什么我喜欢长格式mtest而不是OP test,即使我回到宽格式进行分析(感谢@Henrik)......

  • 站点可能/应该是一个因素,如果你将它分成核心数据中的两列,确保两个因素具有相同的水平是一个负担。
  • 数据可能是根据事件(如“自行车左侧”和“自行车到达”)记录的,而不是旅行方面。例如,如果有人偷了自行车或丢失了,endtimeend_station在逻辑上应该丢失,但在我看来,这更容易以长格式跟踪。
  • 根据我的经验,测量数据甚至可能连续有两个“自行车到达”事件,即使它在逻辑上没有意义,任何可能出错的数据都会出错。如果发生这种情况,你将很难确定如何以宽幅格式记录行程。

一般来说,我只是应用我对tidy data的理解(可能是过分热心或错误的),在关于数据布局的链接中重复哈德利的抱怨,其中“[c] olumn header是值,而不是变量名。”

答案 1 :(得分:1)

dplyr解决方案:

library(dplyr)
df %>%
  mutate(lag_end_station = lag(end_station),
         lag_end_time = lag(endtime)) %>%
  filter(start_station == "B" & lag_end_station == "B") %>%
  transmute(interval = difftime(starttime, lag_end_time))

<强>结果:

  interval
1 360 mins
2 120 mins
3  30 mins