使用R实现员工考勤记分卡:连续CAOF请假仅扣1分的计算方法
R语言实现CAOF连续请假段计数计分
核心计分规则落地
先把业务规则转成可计算的判定标准,和你给出的示例结果完全对齐:
- 每出现1段无间隔连续的CAOF请假,扣1分,不按请假天数累计
- 连续段的判定:同一员工名下,两条CAOF请假的自然日间隔为1天(即相邻两天),才算同一段;只要两个CAOF记录间隔超过1天、或中间夹了非CAOF的考勤记录,就算独立的两段
- 最终考勤得分 = - 该员工的CAOF连续段总数
分步实现流程(适配基础R学习阶段,代码逐行可理解)
- 第一步:数据基础整理
首先导入原始考勤数据,完成日期格式转换、排序,这步是后续连续段判定的基础:# 以你提供的示例数据为测试用例 raw_data <- data.frame( employee = c("employee1","employee1","employee1","employee1","employee1","employee1"), workdate = c("7/7/19","7/19/19","8/30/19","10/02/19","10/9/19","10/10/19"), reason = c("CAOF","CAOF","PUL","CAOF","CAOF","CAOF") ) # 将字符串格式的日期转为R可识别的Date类型 # 注意format参数要和原始日期格式匹配,%m=月、%d=日、%y=两位年份 raw_data$workdate <- as.Date(raw_data$workdate, format = "%m/%d/%y") # 关键操作:按员工姓名、考勤日期升序排序,不排序无法准确判定连续段 raw_data <- raw_data[order(raw_data$employee, raw_data$workdate), ] - 第二步:逐行标记CAOF连续段的起点
连续段计数的本质,就是统计所有CAOF段的起始位置数量。满足以下所有条件的记录,就是一段CAOF的起点:- 当前记录的reason是CAOF
- 和同员工的上一条考勤记录比,满足任意一条:
- 是该员工的第一条考勤记录,没有上一条
- 上一条记录的reason不是CAOF
- 上一条虽然是CAOF,但两个日期的间隔超过1天
对应基础R的实现代码:
# 提取每条记录对应的上一条记录的信息 # 先标记:当前记录和上一条是否属于同一个员工 raw_data$is_same_emp_prev <- c( FALSE, # 第一条记录没有上一条,默认不是同员工 raw_data$employee[-1] == raw_data$employee[-nrow(raw_data)] ) # 提取上一条记录的reason raw_data$prev_reason <- c( NA, # 第一条记录没有上一条的reason raw_data$reason[-nrow(raw_data)] ) # 提取上一条记录的日期 raw_data$prev_date <- c( NA, # 第一条记录没有上一条的日期 raw_data$workdate[-nrow(raw_data)] ) # 判定当前记录是不是CAOF段的起点 raw_data$is_caof_segment_start <- with( raw_data, reason == "CAOF" & ( !is_same_emp_prev | # 是新员工的第一条记录 prev_reason != "CAOF" | # 上一条不是CAOF (workdate - prev_date) > 1 # 和上一条CAOF的间隔超过1天 ) ) - 第三步:按员工汇总计算最终得分
用基础R自带的分组聚合函数,统计每个员工的CAOF段数,换算成扣分:# 按员工分组,汇总每个员工的CAOF段总数 score_result <- aggregate( is_caof_segment_start ~ employee, data = raw_data, FUN = sum ) # 换算成考勤得分:每段扣1分 score_result$attendance_score <- -score_result$is_caof_segment_start # 调整列名,让结果更易读 names(score_result) <- c("employee", "caof_segment_total", "attendance_score")
结果验证
针对你提供的employee1示例数据,运行完代码后得到的结果为:
| employee | caof_segment_total | attendance_score |
|---|---|---|
| employee1 | 4 | -4 |
和你手动计算的结果完全一致。
实际业务场景适配提示
- 如果你的业务规则中,连续的判定是按工作日计算(即跳过周末、法定节假日),只需要把日期差的判定逻辑从
(workdate - prev_date) >1调整为两个日期之间的工作日间隔数即可 - 导入实际生产数据时,记得提前去掉同一员工同一天的重复考勤记录,避免重复计数
- 如果统计周期有明确的起止范围,记得先把数据过滤到指定周期内,再做连续段判定
内容的提问来源于stack exchange,提问作者Casey Gallaher
相关产品推荐
相关产品推荐

