如何在R中为每行添加对应标签的最新历史ID列
在R中为标签添加最近一次出现的ID列
问题描述
我有如下R数据集:
| ID | tags |
|---|---|
| 1 | A1 |
| 1 | A2 |
| 2 | A1 |
| 2 | B2 |
| 2 | C3 |
| 2 | C4 |
| 3 | A1 |
| 3 | D4 |
| 3 | C3 |
| 3 | A4 |
| 3 | B2 |
| 4 | A2 |
| 4 | B2 |
希望新增一列「Last ID mention」,填入对应标签最近一次出现的ID值,目标效果如下:
| ID | tags | Last ID mention |
|---|---|---|
| 1 | A1 | NA |
| 1 | A2 | NA |
| 2 | A1 | 1 |
| 2 | B2 | NA |
| 2 | C3 | NA |
| 2 | C4 | NA |
| 3 | A1 | 2 |
| 3 | D4 | NA |
| 3 | C3 | 2 |
| 3 | A4 | NA |
| 3 | B2 | 2 |
| 4 | A2 | 1 |
| 4 | B2 | 3 |
由于每个ID对应的行数不同,我认为无法使用lag()函数,目前主要用dplyr尝试,也试过循环,但不确定这是否是最简洁的方法,请问该如何实现?
解决方案
方法1:dplyr简洁实现
核心思路是先按tags分组,提取每个标签对应的唯一ID序列,对该序列取滞后值后,再映射回原数据集:
library(dplyr) # 构造示例数据 df <- tibble( ID = c(1,1,2,2,2,2,3,3,3,3,3,4,4), tags = c("A1","A2","A1","B2","C3","C4","A1","D4","C3","A4","B2","A2","B2") ) result <- df %>% group_by(tags) %>% mutate( # 标记当前ID在该标签唯一ID序列中的位置 id_pos = match(ID, unique(ID)), # 取该标签唯一ID序列的滞后值,匹配到当前行 `Last ID mention` = lag(unique(ID))[id_pos] ) %>% ungroup() %>% select(ID, tags, `Last ID mention`) print(result)
方法2:data.table高效实现(适合大数据)
如果数据集规模较大,data.table的操作速度更有优势:
library(data.table) setDT(df) # 生成每个标签的唯一ID及其对应上一次出现的ID tag_ref <- df[, .(unique_ID = unique(ID)), by = tags][, `Last ID mention` := shift(unique_ID), by = tags] # 合并回原数据 result <- df[tag_ref, on = .(tags, ID = unique_ID)]
关键说明
普通lag()函数是对分组内的每一行取上一行值,但我们需要的是标签上一次出现的不同ID,而非同一ID内的行滞后。因此必须先提取每个标签的唯一ID序列,对这个序列取滞后,再将结果映射回原数据,这样就能正确得到每个标签最近一次出现的ID。
内容的提问来源于stack exchange,提问作者Mars
相关产品推荐
相关产品推荐

