r根据条件选择日期

时间:2017-07-11 18:13:07

标签: r date datatable dplyr subset

我有一个包含三列的数据集,Id,Code,Date。

Id          Code                 Date
70329       CD_1020              2004-08-25
70329       DSW_46               2005-01-18
70329       AS_712               2009-09-11
1194167     CK_45                2005-10-13
1194167     CD_412               2012-04-12
1194167     DSW_99               2004-08-16
1194167     CD_456               2010-04-18

对于每个Id,列Code将包含许多不同的代码值,但它始终包含值 DSW_46 DSW_99 。无论每个ID存在哪些其他代码值,都会出现DSW_46或DSW_99这两个值。

目标是根据此标准创建第四列。

第1步:在每个Id前面,捕获该行包含DSW_46或DSW_99的日期。

第二步:

a)如果有Id的DSW_46或DSW_99行之前的行,则存储包含DSW_46或DSW_99值的日期。例如:在Id 70329的情况下,存在值为DSW_46的行,相应的日期为2005-01-18,但是在2005-01-18之前有一行用于该ID。因此新日期列应存储日期2005-01-18

b)如果没有比具有DSW_46或DSW_99值的行更早的行,则存储该ID的下一次观察的日期。例如:对于ID 1194167,包含DSW_99的行的日期值为2004-08-16,这是最早的。此id之前没有任何内容(1194167)。所以新的日期列应该存储日期2005.10.13,这是2004-08-16之后的下一个日期。

最终预期数据集如下所示

Id          Code                 Date         NewDate
70329       CD_1020              2004-08-25   2005-01-18
70329       DSW_46               2005-01-18   2005-01-18 
70329       AS_712               2009-09-11   2005-01-18
1194167     CK_45                2005-10-13   2005-10-13
1194167     CD_412               2012-04-12   2005-10-13
1194167     DSW_99               2004-08-16   2005-10-13
1194167     CD_456               2010-04-18   2005-10-13

希望这是有道理的。任何有关如何实现这一目标的帮助都非常感谢。

2 个答案:

答案 0 :(得分:1)

使用dplyr

尝试此ifelse

库(dplyr)

df$Date=as.character(df$Date)
df1=df %>%arrange(Date)%>%group_by(Id)%>% 
    dplyr::mutate(NewDate = ifelse(sum(Date>=Date[Code%in%c('DSW_46','DSW_99')])==length(Date),Date[2] ,Date[Code%in%c('DSW_46','DSW_99')]))

output


Id    Code       Date    NewDate
    <int>   <chr>      <chr>      <chr>
1 1194167  DSW_99 2004-08-16 2005-10-13
2   70329 CD_1020 2004-08-25 2005-01-18
3   70329  DSW_46 2005-01-18 2005-01-18
4 1194167   CK_45 2005-10-13 2005-10-13
5   70329  AS_712 2009-09-11 2005-01-18
6 1194167  CD_456 2010-04-18 2005-10-13
7 1194167  CD_412 2012-04-12 2005-10-13

答案 1 :(得分:0)

另一个dplyr解决方案,使用summariseleft_join

dt <- read.table(text = "Id          Code                 Date
70329       CD_1020              2004-08-25
                 70329       DSW_46               2005-01-18
                 70329       AS_712               2009-09-11
                 1194167     CK_45                2005-10-13
                 1194167     CD_412               2012-04-12
                 1194167     DSW_99               2004-08-16
                 1194167     CD_456               2010-04-18",
                 header = TRUE, stringsAsFactors = FALSE)

library(dplyr)

dt2 <- dt %>% 
  mutate(Date = as.Date(Date)) %>%
  group_by(Id)

dt3 <- dt2 %>%
  filter(Code %in% c("DSW_46", "DSW_99")) %>%
  summarise(Date_DSW = min(Date))

dt4 <- dt2 %>%  
  filter(!Code %in% c("DSW_46", "DSW_99")) %>%
  summarise(Date_min = min(Date))

dt5 <- dt2 %>%
  left_join(dt3, by = "Id") %>%
  left_join(dt4, by = "Id") %>%
  mutate(NewDate = if_else(Date_DSW > Date_min, Date_DSW, Date_min)) %>%
  select(Id, Code, Date, NewDate)