首页 > 解决方案 > 将 dplyr 中的领先或滞后与其他变量结合使用

问题描述

我有一个数据框:

                 Time   CardID    Data      Type
1  2018-01-01 10:44:35 10037479 PowerOn  STBEvent
2  2018-01-01 10:44:48 10037479    0401 UseRemote
3  2018-01-01 10:44:53 10037479    0301 UseRemote
4  2018-01-01 10:45:13 10037479    0401 UseRemote
5  2018-01-01 10:45:24 10037479    0301 UseRemote
6  2018-01-01 10:45:30 10037479    1415  LiveView
7  2018-01-01 10:45:37 10037479    0401 UseRemote
8  2018-01-01 11:08:01 10037479    1412  LiveView
9  2018-01-01 11:08:13 10037479    0401 UseRemote
10 2018-01-01 11:14:31 10037479    0301 UseRemote

structure(list(Time = structure(c(1514783675, 1514783688, 1514783693, 
1514783713, 1514783724, 1514783730, 1514783737, 1514785081, 1514785093, 
1514785471), class = c("POSIXct", "POSIXt")), CardID = c("10037479", 
"10037479", "10037479", "10037479", "10037479", "10037479", "10037479", 
"10037479", "10037479", "10037479"), Data = c("PowerOn", "0401", 
"0301", "0401", "0301", "1415", "0401", "1412", "0401", "0301"
), Type = c("STBEvent", "UseRemote", "UseRemote", "UseRemote", 
"UseRemote", "LiveView", "UseRemote", "LiveView", "UseRemote", 
"UseRemote")), .Names = c("Time", "CardID", "Data", "Type"), row.names = c(NA, 
10L), class = "data.frame")

我正在使用 dplyr 中的超前和滞后函数来获取特定行之前和之后的数据点。例如我正在使用这个:

ae1 <- which(dplyr::lag(df$Data)=="1415")+1

这让我从上面的数据框中获得第 6 行,其中类型等于“LiveView”。我理解通过更改代码末尾的整数,我可以从数据框中获取相应的行。我的问题是:我可以使用相同/相似的功能,其中我可以在下一个“LiveView”中获取数据 - 这是第 8 行。我可以很好地做到

ae1 <- which(dplyr::lag(df$Data)=="1415")+3

获得第 8 行。但是下一个 LiveView 类型可以出现在第 8 行以外的任何行中。我在想类似于

ae1 <- which(dplyr::lag(df$Data)=="1415")+nrow(where Type == next "LiveView")

标签: rdplyr

解决方案


我正在使用 dplyr 中的超前和滞后函数来获取特定行之前和之后的数据点。[...] 我可以使用相同/相似的功能,其中我可以在下一个“LiveView”中获取数据[?]

如果对于 Data == 1415 的每个实例,您想要找到 CardID 匹配、Type 匹配且 Time 更大的下一行,那么...

library(data.table)
setDT(df)

mdf = df[Data == "1415", .(CardID, Type, Time)]
w   = df[mdf, on=.(CardID, Type, Time > Time), mult="first", which=TRUE]
df[w]

#                   Time   CardID Data     Type
# 1: 2018-01-01 00:38:01 10037479 1412 LiveView

如果您有重复的时间,则Time不能作为行号。您可以添加行号,例如df[, rn := .I]ordf[, rn := rowid(CardID)]并使用它。

这条线on=是一个非 equi 连接,目前在 dplyr 中不可用,这就是为什么我在这里发布一个不同的包。


如果你想返回两行......

w0 = df[Data == "1415", which=TRUE]
w  = df[df[w0], on=.(CardID, Type, Time > Time), mult="first", which=TRUE]
df[matrix(c(w0, w), 2, byrow=TRUE)]

#                   Time   CardID Data     Type
# 1: 2018-01-01 00:15:30 10037479 1415 LiveView
# 2: 2018-01-01 00:38:01 10037479 1412 LiveView

或者,如果您还想要行前的数据点:

wb = df[df[w0], on=.(CardID, Type, Time < Time), mult="first", which=TRUE]
df[matrix(c(wb, w0, w), 3, byrow=TRUE)]

#                   Time   CardID Data     Type
# 1:                <NA>     <NA> <NA>     <NA>
# 2: 2018-01-01 00:15:30 10037479 1415 LiveView
# 3: 2018-01-01 00:38:01 10037479 1412 LiveView

显示 NA,因为没有行符合这些标准。


推荐阅读