我有一个包含三列的数据集,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
希望这是有道理的。任何有关如何实现这一目标的帮助都非常感谢。
答案 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
解决方案,使用summarise
和left_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)