基于数据框列的企业周期分组识别(R语言dplyr实现问题)
用dplyr生成符合规则的企业时序周期列
需求说明
现有n家企业的时序数据,包含DATE、firm、var三列,需要生成cycle列,规则为:一组连续非零值(可正可负)加上紧随其后的若干零值,属于同一个周期。示例数据如下:
| DATE | firm | var | cycle |
|---|---|---|---|
| 1 | 1 | 2 | 1 |
| 2 | 1 | 3 | 1 |
| 3 | 1 | 4 | 1 |
| 4 | 1 | 0 | 1 |
| 5 | 1 | 0 | 1 |
| 6 | 1 | 3 | 2 |
| 7 | 1 | 4 | 2 |
| 8 | 1 | 5 | 2 |
| 9 | 1 | 7 | 2 |
| 11 | 1 | 0 | 2 |
| 12 | 1 | 0 | 2 |
| 13 | 1 | 1 | 3 |
| 14 | 1 | 2 | 3 |
现有代码问题
你当前的代码基于some_tmp_var的变化生成分组,会把非零段和后续的零段分成不同周期,不符合需求。
正确实现代码
我们可以利用data.table的rleid函数(用于识别连续重复分组)结合cumsum来实现需求,代码如下:
library(dplyr) library(data.table) # 假设你的数据框名为data data <- data %>% ungroup() %>% group_by(firm) %>% # 生成初始连续分组:连续非零/连续零各为一组 mutate(grp = rleid(var != 0)) %>% # 标记当前行是否属于非零组 mutate(is_non_zero = var != 0) %>% # 累加非零组的出现次数,零组会继承前一个非零组的周期号 mutate(cycle = cumsum(is_non_zero)) %>% # (可选)处理开头就是零的特殊情况,这里设为0,可根据需求调整 mutate(cycle = ifelse(cycle == 0, 0, cycle)) %>% # 移除临时辅助列 select(-grp, -is_non_zero) %>% ungroup()
代码解释
- 按企业分组:确保每个企业的时序数据独立处理,避免跨企业的周期混乱。
- 初始连续分组:
rleid(var != 0)将连续的非零值、连续的零值分别划分为不同的临时分组。 - 非零组标记:
is_non_zero标记当前行是否属于非零值组。 - 生成周期号:
cumsum(is_non_zero)会在每次遇到非零组时累加计数,后续的零组因为is_non_zero为0,计数保持不变,正好实现“非零段+后续零段为同一周期”的规则。 - 特殊情况处理:如果数据开头就是零值,
cycle会被设为0,你可以根据实际需求改为NA或其他值。
内容的提问来源于stack exchange,提问作者AdamsConchallos
相关产品推荐
相关产品推荐

