基于参考日期的R语言数据清洗:按年度分配居住地址
R语言实现地址年度分配与数据重排
原始数据集
mydata<-data.frame(id = c("R007", "R008", "R008", "R009", "R009"), statenumber= c(1, 2, 3, 4, 5), startdate = c(20080101, 20080101, 20120301,20120101, 20121001), enddate = c(20121201, 20120301, 20121201, 20121001, 20121201)) # 转换日期格式 mydata$startdate<-as.Date(as.character(mydata$startdate), "%Y%m%d") mydata$enddate<-as.Date(as.character(mydata$enddate), "%Y%m%d")
数据集说明
- ID为R007的人2008-2012年居住在同一地址;
- ID为R008的人2008-2011年居住在地址2,2012年居住在地址3;
- ID为R009的人2012年上半年居住在地址4,最后两个月居住在地址5。
需求
以6月为参考月,若某人6月居住在某地址,则将该地址分配为其全年的地址,最终将数据集重排为每人每年一行的格式,目标结果如下:
endresult<-data.frame(id = c("R007", "R007","R007","R007","R007", "R008", "R008", "R008", "R008","R008", "R009"), statenumber = c(1,1,1,1,1,2,2,2,2,3,4), year = c(2008, 2009, 2010, 2011, 2012, 2008,2009,2010,2011,2012, 2012))
实现方案
可以通过以下步骤完成转换,这里使用dplyr、tidyr和lubridate包简化操作(未安装的话先运行install.packages(c("dplyr", "tidyr", "lubridate", "purrr"))):
library(dplyr) library(tidyr) library(lubridate) library(purrr) # 1. 生成每个居住记录覆盖的所有年份并展开 mydata <- mydata %>% mutate( start_year = year(startdate), end_year = year(enddate), year = map2(start_year, end_year, seq) ) %>% unnest(year) # 2. 生成每年的6月1日作为参考日期 mydata <- mydata %>% mutate(ref_date = as.Date(paste0(year, "-06-01"))) # 3. 筛选参考日期落在居住时段内的记录,同一人同一年仅保留一条 result <- mydata %>% filter(ref_date >= startdate & ref_date <= enddate) %>% group_by(id, year) %>% slice(1) %>% ungroup() %>% select(id, statenumber, year) %>% arrange(id, year)
代码解释
- 生成覆盖年份:通过
map2和seq生成每个居住记录覆盖的年份范围,再用unnest将年份序列展开为每行对应一个年份; - 设置参考日期:为每个年份生成当年6月1日,作为判断居住地址的基准;
- 筛选有效记录:判断参考日期是否处于该条居住记录的时间区间内,保留符合条件的记录,确保同一人同一年仅保留一条;
- 整理结果:选择需要的列并按ID、年份排序,得到目标格式。
验证结果
运行代码后,result的结构与内容和目标数据集完全一致:
> result # A tibble: 11 × 3 id statenumber year <chr> <dbl> <int> 1 R007 1 2008 2 R007 1 2009 3 R007 1 2010 4 R007 1 2011 5 R007 1 2012 6 R008 2 2008 7 R008 2 2009 8 R008 2 2010 9 R008 2 2011 10 R008 3 2012 11 R009 4 2012
内容的提问来源于stack exchange,提问作者Albert
相关产品推荐
相关产品推荐

