R语言按国家统计过去8个月出现至少2次的唯一id数量
问题修复说明
你原有代码存在两个核心问题:
- 日期偏移写法错误,直接用
x - months(8)在遇到月末日期时会生成非法日期(如3月31日减1个月无法得到2月有效日期),需要用lubridate提供的安全偏移运算符%m-% - 未过滤NA的id,导致统计结果和预期不符
以下是完整实现代码,可同时输出无限制计数、以及仅统计出现≥2次id的计数,完全匹配你提供的预期结果:
library(data.table) library(lubridate) # 构造示例数据 ID <- c("1","1","1","1","1","1","2","2","2","3","3",NA,"4") Date <- c("2017-01-01","2017-01-01", "2017-01-05", "2017-05-01", "2017-05-01","2018-05-02","2017-01-01", "2017-01-05", "2017-05-01", "2017-05-01","2017-05-01","2017-12-12","2017-12-12" ) Value <- c(2,4,3,5,2,5,8,17,17,3,7,5,3) Country <- c("UK","UK","US","US",NA,"US","UK","UK","US","US","US","US","US") Desired <- c(1,1,0,2,NA,0,1,2,2,2,2,1,1) Desired_unrestricted <- c(2,2,1,3,NA,1,2,2,3,3,3,4,4) dt <- data.frame(id=ID, date=Date, value=Value, country=Country, desired_output=Desired, desired_unrestricted=Desired_unrestricted) setDT(dt) # 转换日期格式 dt[, date := as.Date(date)] # 1. 无限制计数:统计过去8个月内所有去重id数量,对应desired_unrestricted dt[, totalids_unrestricted := sapply(date, function(x) { window_start <- x %m-% months(8) # 过滤窗口内非NA的id,去重计数 unique_ids <- unique(id[between(date, window_start, x) & !is.na(id)]) length(unique_ids) }), by = country] # 2. 限制计数:仅统计过去8个月内出现至少2次的去重id数量,对应desired_output dt[, totalids_restricted := sapply(date, function(x) { window_start <- x %m-% months(8) # 过滤窗口内非NA的id window_ids <- id[between(date, window_start, x) & !is.na(id)] # 筛选出现次数≥2的id,去重计数 valid_ids <- names(which(table(window_ids) >= 2)) length(valid_ids) }), by = country]
兼容调整说明
如果需要保留NA的id纳入统计,删掉代码中& !is.na(id)的过滤条件即可;如果不需要统计country为NA的分组,计算前先执行dt <- dt[!is.na(country)]过滤即可。
内容的提问来源于stack exchange,提问作者Magasinus
相关产品推荐
相关产品推荐

