我有一个数据帧:
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行,其中Type等于“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")
1)如果目标是找到第一个1415行之后的第一个LiveWire
行的行号,则使用显示的连接,然后使用which
和first
来获取行号和第一个行号。请注意,cummany
对于1415年以来的第一个Data
组件是正确的,并且通过滞后我们只对那些在它结束之后的那些组成。如果我们知道只有一个这样的行,那么我们可以省略first
。由于dplyr的滞后与基地中的lag
冲突,我们使用dplyr::lag
来确保我们使用所需的。
df %>%
{ dplyr::lag(cumany(.$Data == 1415)) & .$Type == "LiveView" } %>%
which %>%
first
## [1] 8
2)如果我们想要行本身而不是使用filter
和slice
。如果我们知道只有一个这样的行,我们可以省略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中的前导和滞后函数来获取特定行之前和之后的数据点。 [...]我可以使用相同/类似的功能,我可以在下一个“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]
或df[, 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。
一种方法是dplyr::group_by
基于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)