R 折叠带条件的日期字段
R collapse date fields with conditions
我有一个如下所示的数据集:
df=data.frame(c(1,2,2,2,3,4,4),
as.Date(c("2015-01-29","2015-02-02","2015-02-02","2015-02-02","2014-05-04","2014-05-04","2014-05-04")),
as.Date(c( "2010-10-01","2009-09-01","2014-01-01","2014-02-01","2009-01-01","2014-03-01","2013-03-01")),
as.Date(c("2016-04-30","2013-12-31","2014-01-31","2016-04-30","2014-02-28","2014-08-31","2013-05-01")));
names(df)=c('id','poi','start','end')
> df
id poi start end
1 1 2015-01-29 2010-10-01 2016-04-30
2 2 2015-02-02 2009-09-01 2013-12-31
3 2 2015-02-02 2014-01-01 2014-01-31
4 2 2015-02-02 2014-02-01 2016-04-30
5 3 2014-05-04 2009-01-01 2014-02-28
6 4 2014-05-04 2014-03-01 2014-08-31
7 4 2014-05-04 2013-03-01 2013-05-01
开始和结束日期是保险开始和结束日期,有时多行的开始日期相同,因为它们
对应不同的保险类型。我有兴趣保留那些具有一致保险的 ID
poi 前后一年的保险。每个ID只能有1个poi
我的输出将是一个 ID 列表,这些 ID 在 poi 前 1 年和 1 年 post 都有保险。在这种情况下,它会排除 id 3 和 4,因为它们在 poi 后 1 年没有覆盖。
ids=c(1,2)
我尝试了以下方法,但老实说我不知道如何实现我想要的。
任何帮助将不胜感激。
library(rehape2)
df.melt=melt(df,
id=c("id","poi"))
df.melt=mutate(df.melt, flag=ave(id,id,variable,FUN=seq_along))
df.melt=mutate(df.melt, variable=paste(variable,flag,sep ="_"))
df.cast=dcast(df.melt, id+poi~variable)
我认为这可以满足您的需求,但如果没有,您应该可以使用大于号和小于号:
df[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1,]
> df[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1,]
id poi start end
1 1 2015-01-29 2010-10-01 2016-04-30
4 2 2015-02-02 2014-02-01 2016-04-30
这为您提供了 df 的两行,其中包含您想要的值..
现在只有 ID 的:
df$id[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1]
df$id[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1]
[1] 1 2
如果您想单独评估行,使用 dplyr
和 lubridate
:
library(dplyr)
library(lubridate)
# filter to only rows with a POI within the desired range
df %>% filter(poi - years(1) >= start,
poi + years(1) <= end)
# id poi start end
# 1 1 2015-01-29 2010-10-01 2016-04-30
# 2 2 2015-02-02 2014-02-01 2016-04-30
如果您更愿意为一个 ID 评估所有行,可能类似于
# group to summarize IDs separately
df %>% group_by(id, poi) %>%
# collapse rows to min start and max end for each ID
summarise(start = min(start),
end = max(end)) %>%
# filter to only rows with a POI within the desired range
filter(poi - years(1) >= start,
poi + years(1) <= end)
# Source: local data frame [2 x 4]
# Groups: id [2]
#
# id poi start end
# (dbl) (date) (date) (date)
# 1 1 2015-01-29 2010-10-01 2016-04-30
# 2 2 2015-02-02 2009-09-01 2016-04-30
不过,如果可能的话,这种方法会忽略覆盖范围内的差距。如果是这样,lubridate::interval
和 int_overlaps
可能有助于仔细压缩行。
我有一个如下所示的数据集:
df=data.frame(c(1,2,2,2,3,4,4),
as.Date(c("2015-01-29","2015-02-02","2015-02-02","2015-02-02","2014-05-04","2014-05-04","2014-05-04")),
as.Date(c( "2010-10-01","2009-09-01","2014-01-01","2014-02-01","2009-01-01","2014-03-01","2013-03-01")),
as.Date(c("2016-04-30","2013-12-31","2014-01-31","2016-04-30","2014-02-28","2014-08-31","2013-05-01")));
names(df)=c('id','poi','start','end')
> df
id poi start end
1 1 2015-01-29 2010-10-01 2016-04-30
2 2 2015-02-02 2009-09-01 2013-12-31
3 2 2015-02-02 2014-01-01 2014-01-31
4 2 2015-02-02 2014-02-01 2016-04-30
5 3 2014-05-04 2009-01-01 2014-02-28
6 4 2014-05-04 2014-03-01 2014-08-31
7 4 2014-05-04 2013-03-01 2013-05-01
开始和结束日期是保险开始和结束日期,有时多行的开始日期相同,因为它们 对应不同的保险类型。我有兴趣保留那些具有一致保险的 ID poi 前后一年的保险。每个ID只能有1个poi
我的输出将是一个 ID 列表,这些 ID 在 poi 前 1 年和 1 年 post 都有保险。在这种情况下,它会排除 id 3 和 4,因为它们在 poi 后 1 年没有覆盖。
ids=c(1,2)
我尝试了以下方法,但老实说我不知道如何实现我想要的。
任何帮助将不胜感激。
library(rehape2)
df.melt=melt(df,
id=c("id","poi"))
df.melt=mutate(df.melt, flag=ave(id,id,variable,FUN=seq_along))
df.melt=mutate(df.melt, variable=paste(variable,flag,sep ="_"))
df.cast=dcast(df.melt, id+poi~variable)
我认为这可以满足您的需求,但如果没有,您应该可以使用大于号和小于号:
df[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1,]
> df[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1,]
id poi start end
1 1 2015-01-29 2010-10-01 2016-04-30
4 2 2015-02-02 2014-02-01 2016-04-30
这为您提供了 df 的两行,其中包含您想要的值..
现在只有 ID 的:
df$id[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1]
df$id[(df$poi-df$start)/365>1&(df$end-df$poi)/365>1]
[1] 1 2
如果您想单独评估行,使用 dplyr
和 lubridate
:
library(dplyr)
library(lubridate)
# filter to only rows with a POI within the desired range
df %>% filter(poi - years(1) >= start,
poi + years(1) <= end)
# id poi start end
# 1 1 2015-01-29 2010-10-01 2016-04-30
# 2 2 2015-02-02 2014-02-01 2016-04-30
如果您更愿意为一个 ID 评估所有行,可能类似于
# group to summarize IDs separately
df %>% group_by(id, poi) %>%
# collapse rows to min start and max end for each ID
summarise(start = min(start),
end = max(end)) %>%
# filter to only rows with a POI within the desired range
filter(poi - years(1) >= start,
poi + years(1) <= end)
# Source: local data frame [2 x 4]
# Groups: id [2]
#
# id poi start end
# (dbl) (date) (date) (date)
# 1 1 2015-01-29 2010-10-01 2016-04-30
# 2 2 2015-02-02 2009-09-01 2016-04-30
不过,如果可能的话,这种方法会忽略覆盖范围内的差距。如果是这样,lubridate::interval
和 int_overlaps
可能有助于仔细压缩行。