如何基于条件填充DataFrame最小time行的NA测试分数并去重ID
解决方案
用dplyr就能搞定,直接看完整代码和解释:
library(dplyr) df %>% group_by(IDs) %>% arrange(time, .by_group = TRUE) %>% # 每个ID组里按时间从小到大排好序 mutate(filled_score = first(na.omit(`test score`))) %>% # 捞取组里第一个不是NA的分数(最小时间行是NA的话,就取次小行的) filter(time == min(time)) %>% # 留下每个ID时间最小的那一行 mutate(`test score` = ifelse(is.na(`test score`), filled_score, `test score`)) %>% # 把NA替换成刚才捞的分数 select(-filled_score) %>% # 删掉临时用的列 ungroup()
代码逻辑说明
arrange(...):先给每个ID的行按时间排序,最小时间的行在前,次小的紧跟,保证后续找分数的顺序正确。mutate(filled_score...):na.omit剔除组内所有NA的分数,first取剩下的第一个值——如果最小时间行的分数是NA,这个值就是次小时间行的分数;如果最小时间行本身有分数,就取它自己,不会出错。filter(...):和你之前写的逻辑一致,保留每个ID对应时间最小的行。- 最后的
mutate完成NA填充,再删掉临时列、取消分组,得到干净的结果。
示例验证
假设你的测试数据是这样:
df <- tibble( IDs = c("A", "A", "B", "B"), time = c(1, 2, 1, 2), `test score` = c(NA, 5, 8, NA) )
运行代码后输出结果:
# A tibble: 2 × 3 IDs time `test score` <chr> <dbl> <dbl> 1 A 1 5 2 B 1 8
完全符合需求:ID A最小时间行的NA被填充为次小行的5,ID B最小时间行的分数保留原值8。
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

