使用dplyr处理HR人事数据:筛选行与补全非连续时间
处理HR岗位人事变动数据集的两个任务解决方案
以下基于R语言的tidyverse生态给出实操方案,假设你的数据集名为hr_data,且日期字段已转换为Date类型。
问题1:按positionID分组,保留第一个非NA exitCode及之后的所有行
先确保数据按岗位和变动时间排序,再标记并筛选目标行:
library(tidyverse) library(lubridate) # 处理问题1:保留每组第一个非NA exitCode及后续行 hr_data_cleaned <- hr_data %>% arrange(positionID, moveStartDate) %>% group_by(positionID) %>% mutate( # 标记从第一个非NA exitCode开始的所有行 keep_flag = cumsum(!is.na(exitCode)) >= 1, # 若组内全为NA exitCode,默认保留所有行(可根据需求修改为FALSE) keep_flag = ifelse(all(is.na(exitCode)), TRUE, keep_flag) ) %>% filter(keep_flag) %>% select(-keep_flag) %>% ungroup()
关键逻辑说明
- 先按
positionID和moveStartDate排序,保证变动顺序正确 - 用
cumsum生成标记:从第一个非NA的exitCode开始,后续所有行都会被标记为TRUE - 针对全组无有效
exitCode的情况,可自行调整是否保留
问题2:补同一positionID下的非连续时间段
基于问题1的结果,补全岗位变动间隙的空缺时间段:
# 处理问题2:补全岗位变动的时间间隙 hr_data_final <- hr_data_cleaned %>% arrange(positionID, moveStartDate) %>% group_by(positionID) %>% mutate( # 获取下一行的变动开始日期 next_start = lead(moveStartDate), # 计算当前行结束到下一行开始的间隔天数 gap_days = as.integer(next_start - moveEndDate) ) %>% # 筛选出需要补全的间隔(间隔>1天才算非连续) filter(gap_days > 1) %>% rowwise() %>% mutate( # 生成间隙内的所有日期 fill_dates = list(seq(moveEndDate + days(1), next_start - days(1), by = "day")), # 补全行的业务字段(可根据实际需求调整) moveType = "岗位空缺", personID = NA, exitCode = NA ) %>% unnest(fill_dates) %>% # 对齐原数据的列结构 rename(moveStartDate = fill_dates, moveEndDate = fill_dates) %>% select(names(hr_data_cleaned)) %>% ungroup() %>% # 合并原数据与补全行,重新排序 bind_rows(hr_data_cleaned) %>% arrange(positionID, moveStartDate)
关键逻辑说明
- 先计算每行与下一行的时间间隙,仅处理间隔超过1天的情况(连续日期无需补全)
- 补全行的
moveType设为"岗位空缺",personID和exitCode设为NA,可根据业务规则修改字段值 - 最后合并原数据与补全行,保证整体时间序列连续
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

