按分组与日期统计分类变量:计算员工累计任职岗位数
分组统计员工累计任职不同岗位数量的实现方法
原始数据集
| 日期(date) | 姓名(name) | 岗位名称(rolename) |
|---|---|---|
| 2009-12-01 | John | helper |
| 2010-12-01 | John | helper |
| 2011-12-01 | John | senior helper |
| 2012-12-01 | John | manager |
| 2009-12-01 | Will | helper |
| 2010-12-01 | Will | senior helper |
| 2011-12-01 | Will | manager |
| 2012-12-01 | Will | senior manager |
需求说明
基于name列分组,统计每位员工截至对应date日期时,累计任职过的不同rolename岗位数量,新增nopositions列,目标效果如下:
目标数据集
| 日期(date) | 姓名(name) | 岗位名称(rolename) | 累计岗位数(nopositions) |
|---|---|---|---|
| 2009-12-01 | John | helper | 1 |
| 2010-12-01 | John | helper | 1 |
| 2011-12-01 | John | senior helper | 2 |
| 2012-12-01 | John | manager | 3 |
| 2009-12-01 | Will | helper | 1 |
| 2010-12-01 | Will | senior helper | 2 |
| 2011-12-01 | Will | manager | 3 |
| 2012-12-01 | Will | senior manager | 4 |
失败尝试代码
#attempt 1 library(dplyr) data %>% group_by(name) %>% mutate(nopositions = count(rolename)) #attempt2 library(runner) data %>% group_by(name) %>% mutate(nopositions = runner(x = rolename, k = inf, idx = date, f = function(x) length(x))
正确实现方法
方法一:dplyr原生实现(无需额外包)
核心思路是标记每个岗位首次出现的顺序,再用累积最大值得到累计不同岗位数:
library(dplyr) data %>% group_by(name) %>% arrange(date) %>% # 确保按日期顺序处理 mutate( # 标记每个岗位在当前员工序列中的首次出现位次 first_pos = match(rolename, unique(rolename)), # 累积取最大值,得到截至当前日期的累计岗位数 nopositions = cummax(first_pos) ) %>% select(-first_pos) %>% # 移除中间辅助列 ungroup()
方法二:结合purrr的直观实现
通过逐行统计当前行及之前的去重岗位数量:
library(dplyr) library(purrr) data %>% group_by(name) %>% arrange(date) %>% mutate(nopositions = map_int(row_number(), ~length(unique(rolename[1:.x])))) %>% ungroup()
方法三:修正runner包的使用
原runner尝试的问题是未对岗位去重,修正后代码如下:
library(runner) library(dplyr) data %>% group_by(name) %>% arrange(date) %>% mutate(nopositions = runner( x = rolename, k = Inf, # 取从开头到当前行的所有数据 f = function(x) length(unique(x)) # 统计去重后的岗位数量 )) %>% ungroup()
关键注意点
- 所有方法必须先对
date排序,否则累积统计的顺序会出错 - 分组仅针对
name,确保只统计同一员工的岗位记录
内容的提问来源于stack exchange,提问作者fsure
相关产品推荐
相关产品推荐

