如何在R中实现Stata的expand功能按工作年份扩展数据行?
在R中实现Stata的
expand功能:按工作年份拆分数据行 我有一份包含参与者ID、工作编号、工作开始日期、工作结束日期的数据集,想要为每份工作的每个工作年份新增一行。已知Stata中可以用expand finish_time-start_time + 1实现,但我用R语言,不知道怎么实现相同需求。
示例数据
data <- data.frame(id = c(1,1,2,3), job = c(1,2,1,1), start_time = seq(as.Date('2017-01-01'), as.Date('2020-01-01'), by = 'years'), finish_time = seq(as.Date('2020-12-01'), as.Date('2023-12-01'), by = 'years'))
预期输出
每条原始数据行扩展为对应年份数量的行,新增expand列标记序号,示例格式如下:
| id | job | start_time | finish_time | expand |
|---|---|---|---|---|
| 1 | 1 | 2017-01-01 | 2020-12-01 | 1 |
| 1 | 1 | 2017-01-01 | 2020-12-01 | 2 |
| 1 | 1 | 2017-01-01 | 2020-12-01 | 3 |
| 1 | 1 | 2017-01-01 | 2020-12-01 | 4 |
| 1 | 2 | 2018-01-01 | 2021-12-01 | 1 |
| ... | ... | ... | ... | ... |
解决方案
方法1:使用tidyverse(dplyr + tidyr)
通过计算年份差生成扩展次数,再拆分列表实现行扩展:
library(tidyverse) data_expanded <- data %>% # 计算需扩展的行数(年份差+1) mutate(expand_count = lubridate::year(finish_time) - lubridate::year(start_time) + 1) %>% # 生成每行对应的序号列表 mutate(expand = map(expand_count, ~1:.x)) %>% # 拆分列表为多行 unnest(expand) %>% # 移除临时计算列 select(-expand_count) print(data_expanded)
若不想依赖lubridate,可替换年份提取逻辑为:as.POSIXlt(start_time)$year + 1900。
方法2:使用base R
无需额外包,通过行索引重复和序号生成实现:
# 计算每行扩展行数 expand_counts <- as.integer(format(data$finish_time, "%Y")) - as.integer(format(data$start_time, "%Y")) + 1 # 生成重复的行索引 row_indices <- rep(seq(nrow(data)), expand_counts) # 扩展数据框并添加序号列 data_expanded_base <- data[row_indices, ] data_expanded_base$expand <- unlist(lapply(expand_counts, seq_len)) print(data_expanded_base)
方法3:使用data.table(大数据高效处理)
针对大型数据集,data.table的实现速度更优:
library(data.table) setDT(data)[, .(expand = 1:(year(finish_time) - year(start_time) + 1)), by = .(id, job, start_time, finish_time)]
内容的提问来源于stack exchange,提问作者Miquel Vallbona
相关产品推荐
相关产品推荐

