按组用对应位置值填充s1、s2缺失值的dplyr实现求助
按组用对应位置值填充缺失值的解决方案
嘿,我来帮你搞定这个按组处理缺失值的问题!根据你的描述,你需要按id分组,用同组内相同相对位置的vals/vals2值,替换s1和s2中的缺失值。先看你生成的测试数据:每组前2个s1是NA(因为rollsumr(vals, k=3)需要3个连续值,前两个位置没法计算),每组第一个s2是NA(rollsumr(vals, k=2)需要2个连续值)。
下面给你几种可行的实现方法:
方法1:用dplyr实现(最贴合你的需求场景)
这是最直接的dplyr写法,分组后逐行检查缺失值,用同位置的vals/vals2替换:
library(dplyr) # 先运行你提供的数据生成代码 id = c(1,1,1,1,1,1,2,2,2,2) date=101:110 vals = c(101:110) vals2 = c(1:10) test = data.frame(id,date,vals,vals2) test <- test %>% group_by(id) %>% mutate(s1=rollsumr(vals,k=3,fill=NA), s2=rollsumr(vals,k=2,fill=NA)) # 核心填充逻辑 test_filled <- test %>% group_by(id) %>% mutate( # 当s1为NA时,用同组同位置的vals替换 s1 = if_else(is.na(s1), vals, s1), # 当s2为NA时,用同组同位置的vals2替换 s2 = if_else(is.na(s2), vals2, s2) ) %>% ungroup() # 查看结果 print(test_filled)
如果你的需求是用vals和vals2的组合(比如相加)替换,只需要把vals改成vals + vals2即可。
方法2:用data.table实现(适合大数据场景)
如果你的数据集很大,data.table的分组操作效率会更高:
library(data.table) # 转换为data.table格式 setDT(test) # 按id分组填充 test_filled_dt <- test[, `:=`( s1 = fifelse(is.na(s1), vals, s1), s2 = fifelse(is.na(s2), vals2, s2) ), by = id ]
方法3:用base R实现(无需额外包)
如果你不想加载第三方包,用base R的ave函数也能实现:
# 填充s1 test$s1_filled <- ave(test$s1, test$id, FUN = function(x) { # 找到组内NA的位置,用对应位置的vals替换 na_pos <- is.na(x) group_id <- unique(test$id[na_pos]) x[na_pos] <- test$vals[test$id == group_id][na_pos] x }) # 填充s2 test$s2_filled <- ave(test$s2, test$id, FUN = function(x) { na_pos <- is.na(x) group_id <- unique(test$id[na_pos]) x[na_pos] <- test$vals2[test$id == group_id][na_pos] x })
拓展:自定义相对位置替换
如果你的需求不是用当前行的vals/vals2,而是组内其他相对位置的值(比如组内第n个NA用组内第n+1个vals),可以用row_number()定位组内位置:
test %>% group_by(id) %>% mutate( # s1的NA替换成组内下一个位置的vals s1 = if_else(is.na(s1), lead(vals), s1), # s2的NA替换成组内上一个位置的vals2 s2 = if_else(is.na(s2), lag(vals2), s2) ) %>% ungroup()
内容的提问来源于stack exchange,提问作者MLE
相关产品推荐
相关产品推荐

