使用data.table根据使用r的条件对事件进行分组

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 90099010或者说所有那些EVENT 1000,或任意组合.

Mat*_*ock 5

我会用一个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_EVENTNEXT_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)

在问题更新#2之后

我不确定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组(不存在)被调用时会发出警告,但它不会破坏事情.就像我说的,这是一个相当丑陋的解决方案.也许其他人有更好的想法.