我必须在某些日期将满足条件,二元标志的观测值转换为具有日期范围的观测表。
示例数据如下所示:
id <- c(1001, 1001, 1001, 1002, 1002, 1002, 1003, 1003, 1003)
date <- c("2016-06-20", "2016-06-21", "2016-06-22", "2016-06-20",
"2016-06-21", "2016-06-22", "2016-06-20", "2016-06-21",
"2016-06-22")
flag <- c(1, 0, 0, 1, 1, 0, 1, 0, 1)
mydata <- data.frame(id, date, flag)
id date flag
1001 2016-06-20 1
1001 2016-06-21 0
1001 2016-06-22 0
1002 2016-06-20 1
1002 2016-06-21 1
1002 2016-06-22 0
1003 2016-06-20 1
1003 2016-06-21 0
1003 2016-06-22 1
我认为这是一个两步过程。
步骤1:确定标志是否连续出现。
这与此问题类似 - R, find, dates, consecutive - 但条件是flag > 0
。我尝试应用解决方案,虽然它的工作方式不同。
mydata$flag_consecutive <- mydata$flag > 0 & c(NA, diff(as.Date(mydata$date)) == 1)
id date flag flag_consecutive
1001 2016-06-20 1 NA
1001 2016-06-21 0 FALSE
1001 2016-06-22 0 FALSE
1002 2016-06-20 1 FALSE
1002 2016-06-21 1 TRUE
1002 2016-06-22 0 FALSE
1003 2016-06-20 1 FALSE
1003 2016-06-21 0 FALSE
1003 2016-06-22 1 TRUE
第2步:创建日期范围列
我不确定如何在R中使用矢量化来处理这个部分。
如果标志仅在一天发生,则开始和结束日期相同。
如果该标志连续几天发生,我希望将序列中的第一天作为date_start
,将最后一天作为date_end
。如果没有发生标记,请从数据集中删除该标记。
我想要生成的是以这种方式格式化的数据:
id flag date_start date_end
1001 1 2016-06-20 2016-06-20
1002 1 2016-06-20 2016-06-21
1003 1 2016-06-20 2016-06-20
1003 1 2016-06-22 2016-06-22
如果您可以就第1步或第2步提供任何指导,我非常感谢。我在圈子里思考,不确定是否需要第1步。
答案 0 :(得分:2)
使用data.table
- 包的可能解决方案:
library(data.table)
setDT(mydata)[, rl := rleid(flag)
][flag == 1
, .(date_start = first(date), date_end = last(date))
, by = .(id, rl, flag)
][, rl := NULL][]
给出:
id flag date_start date_end 1: 1001 1 2016-06-20 2016-06-20 2: 1002 1 2016-06-20 2016-06-21 3: 1003 1 2016-06-20 2016-06-20 4: 1003 1 2016-06-22 2016-06-22
这是做什么的:
rl := rleid(flag)
为rl
s的每个连续行创建分组变量flag
flag == 1
.(date_start = first(date), date_end = last(date))
选择每个组的第一个和最后一个观察值;当只有一个值时,first
和last
会选择该值。使用dplyr
的等效方法:
library(dplyr)
mydata %>%
mutate(rl = cumsum(flag != lag(flag, default = 1))) %>%
filter(flag == 1) %>%
group_by(id, flag, rl) %>%
summarise(date_start = first(date),
date_end = last(date)) %>%
select(-rl)