如何按行指定不同列执行rowSums()判断前三列是否全为NA
问题解决:根据每行指定列检查前三列是否全为NA
问题根源分析
你原代码的问题主要有三点:
- 列范围错误:需求是检查
colnum的前三列(如colnum=5对应day2-day4,即列索引2-4),但你写的(colnum-1):(colnum+1)是选取colnum的前一列、当前列、后一列,完全偏离需求。 - 逻辑判断错误:
rowSums(..., na.rm=TRUE) ==3是判断三列全为1(NA会被当作0忽略),和你要检查的「全为NA」逻辑相反。 - 逐行操作失效:
select()是对整个数据框批量操作,colnum是多元素向量时,R只会取第一个元素生成列范围,无法实现每行单独指定列。
解决方案(管道流实现)
使用rowwise()配合c_across()实现逐行处理,结合case_when()处理边界情况,直接用all(is.na())判断全NA:
library(dplyr) library(tidyr) # 构建示例数据 toy <- data.frame(id = c(rep(1, 10), rep(2, 10), rep(3, 10)), day = c(1:10, 1:10, 1:10), response = c(1, NA, NA, NA, 1, 1, 1, NA, NA, 1, 1, 1, NA, 1 ,1 ,1 ,1 ,1 ,1, 1, NA, 1, NA, 1, 1, 1, NA, NA, NA, NA), colnum = c(rep(5, 10), rep(7, 10), rep(10, 10))) %>% pivot_wider(names_from = 2, values_from = 3, names_prefix = "day") # 生成目标列three_miss toy <- toy %>% rowwise() %>% mutate(three_miss = case_when( colnum <= 3 ~ NA, # 列数不足3,无法检查前三列 colnum > 10 ~ NA, # 超出最大列索引 TRUE ~ all(is.na(c_across((colnum-3):(colnum-1)))) )) %>% ungroup() # 查看结果 toy
运行后three_miss列的值为FALSE, TRUE, FALSE,完全符合你的预期。
代码说明
rowwise():让后续的mutate按行执行,确保每行使用自己的colnum值计算列范围。c_across((colnum-3):(colnum-1)):根据当前行的colnum,选取对应的前三列。all(is.na(...)):直接判断选中的三列是否全部为NA,逻辑清晰准确。
内容的提问来源于stack exchange,提问作者Reid
相关产品推荐
相关产品推荐

