将dplyr的超前或滞后与其他变量结合使用

将dplyr的超前或滞后与其他变量结合使用,r,dplyr,R,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 Us

我有一个数据帧:

                 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中的lead和lag函数来获取特定行前后的数据点。例如,我使用的是:

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

ae1一种方法是根据
Type
dplyr::filter
感兴趣的
Type
对数据进行分组,然后将
dplyr::slice
切到您想要的位置,在本例中,定位
2

library(dplyr)

df <- 
  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")


df %>% 
group_by(Type) %>% 
filter(Type %in% 'LiveView') %>% 
slice(2)
库(dplyr)
df%
分组依据(类型)%>%
筛选器(在%'LiveView')%%中键入%
切片(2)
1)如果目标是找到经过第一个1415行的第一个
LiveWire
行的行号,则使用所示的连词,后跟
which
first
,以获得行号和这些行号中的第一个。请注意,对于1415年以后的第一个
Data
组件,
cummany
是正确的,通过延迟它,我们只对后面的组件才是正确的。如果我们知道只有一行,那么我们可以先省略
。由于dplyr的滞后与基础中的
lag
冲突,因此我们使用
dplyr::lag
来确保我们使用的是所需的滞后

df %>% 
  { dplyr::lag(cumany(.$Data == 1415)) & .$Type == "LiveView" } %>%
  which %>%
  first
  ## [1] 8
2)如果我们希望使用行本身,则使用
filter
slice
。如果我们知道只有一行,我们就可以省略
片段

df %>% 
  filter(dplyr::lag(cumany(Data == 1415)) & Type == "LiveView") %>%
  slice(1)
##                  Time   CardID Data     Type
## 1 2018-01-01 00:38:01 10037479 1412 LiveView
请注意,如果我们通过将第一行代码替换为以下内容,将行号添加到
df

df %>% mutate(n = 1:n()) %>%
然后,除了其他列中的行之外,上面的代码还将在
n
列中给出行号

2a)对(2)的一种替代方法是,我们可以首先通过
cumany(Data==1415)
进行筛选,从第一行1415开始提供所有行,然后删除第一行,因为我们只需要它后面的行,然后在其中找到
LiveView
行并获取第一行

df %>% 
  filter(cumany(Data == 1415)) %>%
  slice(-1) %>%
  filter(Type == "LiveView") %>%
  slice(1)
##                  Time   CardID Data     Type
## 1 2018-01-01 00:38:01 10037479 1412 LiveView
更新 修订

我使用dplyr中的lead和lag函数来获取特定行前后的数据点。[…]我是否可以使用相同/类似的函数,在该函数中,我可以在下一个“LiveView”中获取数据[?]

如果对于Data==1415的每个实例,您希望找到cardd匹配、Type匹配且时间更大的下一行,那么

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
如果您有重复的时间,
时间
将不能作为行号。您可以添加一个行号,如
df[,rn:=.I]
df[,rn:=rowid(CardID)]
,然后改用它

带有
on=
的行是一个非相等连接,目前在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
wb=df[df[w0],on=(cardd,Type,Time

显示NAs是因为没有行符合这些标准。

您的预期结果有点不清楚。假设您的数据帧名为
df
,可能类似于
groupby(df,Type)%%>%mutate(lag1=lag(data,1))
。还有一个
lead
函数,它朝相反的方向移动。我同意@jdobres。现在还不清楚您要做什么,以及您的预期输出应该是什么样子。请编辑您的问题,以包含您提供的特定样本数据的预期输出,好吗?是的,这一点不清楚。请用文字说明目标。是否要获取行号?划船本身?第一行LiveWire超过了第一行1415?“这得到了第6行”--不,8,当我无论如何运行代码时。
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