基于中点假设逐年累加技能字符串的R语言实现方案
问题描述
我有一份人员-技能及对应技能使用年份的数据集,希望基于「技能获取于两次使用的中点」这一假设,填充年份区间内的技能信息。对base R、tidyverse或data.table工具无偏好。
现有数据集:
have <- data.frame( person = c("A","A","B","B","C","C"), skill = c("S1","S2", "S1,S2","S3","S1,S3","S1,S2" ), year = c(2015,2018,2016,2018,2016,2018) )
期望得到的数据集:
want <- data.frame( person = c("A","A","A","A","B","B","B","C","C","C"), skill = c("S1","S1","S1,S2","S1,S2","S1,S2","S1,S2,S3","S1,S2,S3","S1,S3","S1,S2,S3","S1,S2,S3"), year = c(2015,2016,2017,2018,2016,2017,2018,2016,2017,2018) )
我尝试过用fill(.direction = "down"),但不知道如何反向填充技能,也不清楚怎么对已拥有的技能去重。
解决方案(tidyverse实现)
核心思路是先拆分技能为单个条目,确定每个技能的生效起始年份,再按年份聚合所有生效技能,最后合并成字符串:
library(tidyverse) result <- have %>% # 1. 把逗号分隔的技能拆成单独行 separate_rows(skill, sep = ",") %>% # 2. 按人员分组,为每个技能计算生效起始年份(两次记录的中点向上取整) group_by(person, skill) %>% mutate( start_year = ifelse(n() > 1, ceiling((year + lead(year))/2), year) ) %>% ungroup() %>% # 3. 按人员生成所有需要的连续年份序列 group_by(person) %>% reframe( year = seq(min(year), max(year), by = 1), skill = skill, start_year = start_year ) %>% # 4. 筛选出当前年份已生效的技能 filter(year >= start_year) %>% # 5. 按人员和年份聚合技能,去重后用逗号连接 group_by(person, year) %>% summarise(skill = str_c(sort(unique(skill)), collapse = ","), .groups = "drop") # 查看结果 print(result)
关键步骤说明
- 拆分技能:
separate_rows将多技能条目拆分为单技能行,便于逐个处理技能的生效时间。 - 计算起始年:对有两次记录的技能,取两次年份的中点向上取整作为技能获取时间;仅一次记录的技能,从记录年份开始生效。
- 生成完整年份:为每个人生成从最早到最晚记录年份的所有连续年份,确保无遗漏。
- 筛选生效技能:保留当前年份大于等于技能起始年的条目,符合「中点获取技能」的假设。
- 聚合去重:按人员和年份分组,对技能去重、排序后合并为逗号分隔的字符串,与期望结果完全匹配。
内容的提问来源于stack exchange,提问作者Torin McFarland
相关产品推荐
相关产品推荐

