基于seq列范围填充DataFrame中id列的缺失值
基于序列范围填充DataFrame的缺失值
问题背景
现有如下R DataFrame:
df <- structure(list(group = c("A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B"), seq = c(-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5), id = c(NA, NA, NA, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 5, NA, NA, NA, NA, NA, 8, 8, 8, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 4, NA, NA)), class = "data.frame", row.names = c(NA, -44L))
数据预览:
group seq id 1 A -5 NA 2 A -4 NA 3 A -3 NA 4 A -2 1 5 A -1 1 6 A 0 NA 7 A 1 NA 8 A 2 NA 9 A 3 NA 10 A 4 NA 11 A 5 NA 12 A -5 NA 13 A -4 NA 14 A -3 NA 15 A -2 NA 16 A -1 NA 17 A 0 NA 18 A 1 5 19 A 2 NA 20 A 3 NA 21 A 4 NA 22 A 5 NA 23 B -5 NA 24 B -4 8 25 B -3 8 26 B -2 8 27 B -1 NA 28 B 0 NA 29 B 1 NA 30 B 2 NA 31 B 3 NA 32 B 4 NA 33 B 5 NA 34 B -5 NA 35 B -4 NA 36 B -3 NA 37 B -2 NA 38 B -1 NA 39 B 0 NA 40 B 1 NA 41 B 2 NA 42 B 3 4 43 B 4 NA 44 B 5 NA
需求是:每个group内的seq以-5到5为一个循环块,将每个块内的id缺失值用该块中已有的非NA值填充,期望输出如下:
group seq id 1 A -5 1 2 A -4 1 3 A -3 1 4 A -2 1 5 A -1 1 6 A 0 1 7 A 1 1 8 A 2 1 9 A 3 1 10 A 4 1 11 A 5 1 12 A -5 5 13 A -4 5 14 A -3 5 15 A -2 5 16 A -1 5 17 A 0 5 18 A 1 5 19 A 2 5 20 A 3 5 21 A 4 5 22 A 5 5 23 B -5 8 24 B -4 8 25 B -3 8 26 B -2 8 27 B -1 8 28 B 0 8 29 B 1 8 30 B 2 8 31 B 3 8 32 B 4 8 33 B 5 8 34 B -5 4 35 B -4 4 36 B -3 4 37 B -2 4 38 B -1 4 39 B 0 4 40 B 1 4 41 B 2 4 42 B 3 4 43 B 4 4 44 B 5 4
解决方案
使用dplyr包可以高效实现该需求,步骤如下:
- 按
group分组,识别每个seq循环块(以seq == -5作为块的起始标记) - 在每个块内,用块中唯一的非NA值填充所有
id的缺失
代码实现:
library(dplyr) # 填充缺失值 df_filled <- df %>% group_by(group) %>% # 生成块分组标记:每次seq为-5时累加,区分不同循环块 mutate(block = cumsum(seq == -5)) %>% group_by(group, block) %>% # 用块内第一个非NA的id值替换整个块的id mutate(id = first(na.omit(id))) %>% ungroup() %>% # 移除临时的block列 select(-block) # 查看填充后的结果 print(df_filled)
代码说明
group_by(group):保证不同group的块处理独立cumsum(seq == -5):生成递增的块编号,每个从-5开始的序列被分到同一个块first(na.omit(id)):提取块内所有非NA的id值(假设每个块只有唯一非NA值),并作为整个块的id值select(-block):清理临时生成的块标记列
补充说明
如果每个块内可能存在多个不同的非NAid值,需要先确认数据逻辑,若需取唯一值可改用unique(na.omit(id)),但根据需求描述,每个块应只有一个有效id值,因此上述代码适用。
内容的提问来源于stack exchange,提问作者Quinten
相关产品推荐
相关产品推荐

