Tay*_*lrl 1 grouping if-statement r data.table
我想基于某些标准使用R对数据进行分组.基本上我有一个事件列表,我希望根据相邻行中看到的特定活动模式进行划分.
No. ID DATE_EVENT TIME_EVENT EVENT CODE
102995 018159871 07/08/2014 09:01:57 9008 1111
20398 018159871 07/08/2014 09:01:58 1000 1402
105541 018159871 07/08/2014 09:01:58 9210 1111
63492 018253609 07/08/2014 09:54:26 9008 905
37552 018253609 07/08/2014 09:54:45 9008 1111
9627 018253609 07/08/2014 09:54:48 9210 1111
112700 018253609 07/08/2014 09:54:48 1000 1402
50555 018253609 07/08/2014 09:55:56 1000 1401
63634 018253609 07/08/2014 09:55:56 9210 1111
34551 018330948 07/08/2014 09:21:51 9008 905
47252 018330948 07/08/2014 09:22:15 9008 1111
3975 018330948 07/08/2014 09:22:17 1000 1402
24196 018330948 07/08/2014 09:22:17 9210 1111
111150 018342571 07/08/2014 09:40:08 9008 905
17119 018342571 07/08/2014 09:40:19 9008 1111
18658 018342571 07/08/2014 09:40:21 9210 1111
25654 018342571 07/08/2014 09:40:21 1000 1402
Run Code Online (Sandbox Code Playgroud)
我想对数据进行分组,使得9008和905在一行中,然后在下一行中的9008和1111表示新分组的开始.(如上所示,当这些代码出现时,它位于新ID的开头,但情况并非总是如此,这就是为什么这是必要的)
在下面给出的帮助下,我目前正在使用以下内容
dt[, NEXT_EVENT:=c(tail(EVENT, -1), NA)]
dt[, NEXT_CODE:=c(tail(CODE, -1), NA)]
dt[(EVENT=="9008" & CODE=="905") &
(NEXT_EVENT=="9008" & NEXT_CODE=="1111"),
list(count = .N)]
Run Code Online (Sandbox Code Playgroud)
这给了我2个新列,每个列分别包含以下EVENT andCODE.
看了我的要求之后,我真正需要的是能够根据一组(或一组的集合)将行组合在一起EVENTS.例如,我想能够组合在一起所有要么行9008 9009或9010或者说所有那些EVENT 1000,或任意组合.
我会用一个data.table解决方案.假设上述数据存在于一个data.frame名为df:
dt <- data.table(df)
# dt[<filter>, <do something>, by=<group>]
dt[, NEXT_EVENT:=c(tail(EVENT, -1), NA)]
dt[, NEXT_CODE:=c(tail(CODE, -1), NA)]
dt[(EVENT=="9008" & CODE=="905") &
(NEXT_EVENT=="9008" & NEXT_CODE=="1111"),
list(count = .N)] # replace this with whatever you want to do with the data
Run Code Online (Sandbox Code Playgroud)
你可以做的NEXT_EVENT和NEXT_CODE索引直接在主发言,我分开,使他们更具可读性.
此外,如果您关心许多不同的组合,您可以采取以下措施:
dt[,
list(count = .N),
by=c("EVENT", "CODE", "NEXT_EVENT", "NEXT_CODE")]
Run Code Online (Sandbox Code Playgroud)
可能有些方法可以使用plyr或者做类似的事情dplyr,但我不会那么多地使用这些包.
我可以毫无问题地运行所有东西.我得到了结果
dt[(EVENT=="9008" & CODE=="905") &
(NEXT_EVENT=="9008" & NEXT_CODE=="1111"),
list(count = .N)]
count
1: 3
Run Code Online (Sandbox Code Playgroud)
我在加载时删除了逗号,但将EVENT和CODE转换为字符列.我希望你得到一个结果
count
1: 0
Run Code Online (Sandbox Code Playgroud)
因为你(我认为)比较"9,008"到"9008"(两者都是字符串).
作为一个完整性检查,这是data.table我使用的测试最终看起来像(在执行打印结果的最后一次调用之前)
> dt
No ID DATE_EVENT TIME_EVENT EVENT CODE NEXT_EVENT NEXT_CODE
1: 102995 18159871 07/08/2014 09:01:57 9008 1111 1000 1402
2: 20398 18159871 07/08/2014 09:01:58 1000 1402 9210 1111
3: 105541 18159871 07/08/2014 09:01:58 9210 1111 9008 905
4: 63492 18253609 07/08/2014 09:54:26 9008 905 9008 1111
5: 37552 18253609 07/08/2014 09:54:45 9008 1111 9210 1111
6: 9627 18253609 07/08/2014 09:54:48 9210 1111 1000 1402
7: 112700 18253609 07/08/2014 09:54:48 1000 1402 1000 1401
8: 50555 18253609 07/08/2014 09:55:56 1000 1401 9210 1111
9: 63634 18253609 07/08/2014 09:55:56 9210 1111 9008 905
10: 34551 18330948 07/08/2014 09:21:51 9008 905 9008 1111
11: 47252 18330948 07/08/2014 09:22:15 9008 1111 1000 1402
12: 3975 18330948 07/08/2014 09:22:17 1000 1402 9210 1111
13: 24196 18330948 07/08/2014 09:22:17 9210 1111 9008 905
14: 111150 18342571 07/08/2014 09:40:08 9008 905 9008 1111
15: 17119 18342571 07/08/2014 09:40:19 9008 1111 9210 1111
16: 18658 18342571 07/08/2014 09:40:21 9210 1111 1000 1402
17: 25654 18342571 07/08/2014 09:40:21 1000 1402 NA NA
Run Code Online (Sandbox Code Playgroud)
我不确定data.table是否符合您的新要求.您可以使用下面的代码使其工作,但它不是非常优雅.
dt[,SEQUENCE:=1:.N]
dt[EVENT==9008 & CODE==905 &
NEXT_EVENT==9008 & NEXT_CODE==1111,
GRP_ID:=1:.N]
if (is.na(dt[1, GRP_ID]))
dt[1, GRP_ID:=0]
grps <- dt[!is.na(GRP_ID), unique(GRP_ID)]
for (grp in grps) {
dt[SEQUENCE>max(SEQUENCE[!is.na(GRP_ID) & GRP_ID==grp]) &
SEQUENCE<min(SEQUENCE[!is.na(GRP_ID) & GRP_ID==grp+1]),
GRP_ID:=grp]
}
Run Code Online (Sandbox Code Playgroud)
min当第4组(不存在)被调用时会发出警告,但它不会破坏事情.就像我说的,这是一个相当丑陋的解决方案.也许其他人有更好的想法.