如何用data.table按id分组补全缺失年份并填充freq值为0?
完全可以用data.table实现,实现逻辑和你用dplyr分组合并的思路一致,而且语法更简洁,大数据量下执行效率更高。
实现代码
按每个id自身的起止年份补全(符合你的预期输出要求)
library(data.table) # 你的示例数据 dt <- data.table(id=c('A','A','A','A','B','B','B','B'),year=c(2010,2012,2013,2015,2006,2007,2010,2011),freq=c(2,1,4,3,1,3,5,7)) # 核心实现逻辑 dt_full <- dt[, .(year = min(year):max(year)), by = id][ dt, on = .(id, year), freq := i.freq ][ is.na(freq), freq := 0 ]
代码逻辑说明
- 第一步
dt[, .(year = min(year):max(year)), by = id]:按id分组,为每个id生成从它自身最小记录年份到最大记录年份的连续年份序列,得到所有需要保留的id+year组合 - 第二步
[dt, on = .(id, year), freq := i.freq]:和原始数据表按id、year字段左连接,把原始表中存在的freq值匹配到新的全量序列表中 - 第三步
[is.na(freq), freq := 0]:把匹配不到的缺失年份的freq值统一替换为0
更简洁的写法(使用setnafill函数)
dt_full <- dt[, .(year = min(year):max(year)), by = id] |> merge(dt, by = c("id", "year"), all.x = TRUE) |> setnafill(cols = "freq", fill = 0)
扩展:按全局统一起止年份补全
如果你需要所有id都按照全表的最小年份和最大年份统一补全,用如下写法即可:
global_min_year <- dt[, min(year)] global_max_year <- dt[, max(year)] dt_full <- CJ(id = unique(dt$id), year = global_min_year:global_max_year)[ dt, on = .(id, year), freq := i.freq ][ is.na(freq), freq := 0 ]
内容的提问来源于stack exchange,提问作者Erwan
相关产品推荐
相关产品推荐

