发生事件后从分组数据中删除行

时间:2016-09-30 13:47:31

标签: r dplyr

我有一个包含ID,日期和事件的数据集。事件是二元结果变量。 每个ID最多只能有一个事件。事件之后可能会有更多的0。我想删除组后事件后出现的所有零。我有一个使用下面的dplyr的解决方案,但我很想知道是否有更好的方法。什么是表明事件在过去的某个时刻发生的好方法?

library(dplyr)
d <-as.Date("01-05-15", "%d-%m-%y")
#Starting dataset
df <- data.frame(ID= c(rep(234,4),rep(235,6), rep(237,5)), 
       date = as.Date(c((d-4):(d-1),(d-1):(d+4),(d+1):(d+5)),origin="1960-10-01"),
       event = c(0,1,0,0,0,0,0,0,0,0,0,0,0,1,0))

#desired result
df[c(1:2,5:14),]

#How can Improve this?
df %>% group_by(ID) %>% 
  mutate(cumulative = lag(cumsum(event), default = 0)) %>% 
  filter(cumulative <1) %>% 
  select(-cumulative) %>% ungroup

1 个答案:

答案 0 :(得分:3)

我们可以尝试使用dplyr。按“ID”分组后,检查{event}中的all元素是否为0(all(event == 0))或(|)行序列是否小于或等于'event'(row_number() <= which.max(event))的第一个最大元素,并将该逻辑索引用于filter行。

library(dplyr)
df %>%
   group_by(ID) %>% 
   filter(row_number() <= which.max(event)|all(event==0))
#       ID       date event
#   <dbl>     <date> <dbl>
#1    234 2015-04-27     0
#2    234 2015-04-28     1
#3    235 2015-04-30     0
#4    235 2015-05-01     0
#5    235 2015-05-02     0
#6    235 2015-05-03     0
#7    235 2015-05-04     0
#8    235 2015-05-05     0
#9    237 2015-05-02     0
#10   237 2015-05-03     0
#11   237 2015-05-04     0
#12   237 2015-05-05     1

或者更紧凑的选项是event上的双累积和,等于1并检查filter调用中是否小于2。

df %>%
   group_by(ID) %>% 
   filter(cumsum(cumsum(event == 1))<2)

或使用data.table,将'data.frame'转换为'data.table'(setDT(df)),按'ID'if all分组'event'为0,Subset the Data.table(.SD)或else Subset the Data.table包含从'event'中第一个到第一个最大元素的行。

library(data.table)
setDT(df)[, if(all(event==0)) .SD else .SD[seq(which.max(event))], by = ID]