R语言如何将3列tibble数据合并为2列并剔除每行NA值
R语言提取tibble每行非NA值生成新列方案
场景说明
处理tibble格式数据集时存在固定数据规则:每行3个列中恰好2个存储有效值,剩余1列为NA,需要在保留原有3列的基础上,新增2列存放每行提取出的非NA值。coalesce函数仅支持按优先级返回第一个匹配的非NA值,无法同时提取两个有效值,不能适配该场景。
测试数据
示例输入数据集如下:
library(tibble) input_df <- tibble( col1 = c(NA, 1, 0), col2 = c(1, NA, 1), col3 = c(0, 1, NA) ) input_df # A tibble: 3 × 3 col1 col2 col3 <dbl> <dbl> <dbl> 1 NA 1 0 2 1 NA 1 3 0 1 NA
目标输出为保留全部原列,新增out1、out2列存放每行的两个非NA值:
# A tibble: 3 × 5 col1 col2 col3 out1 out2 <dbl> <dbl> <dbl> <dbl> <dbl> 1 NA 1 0 1 0 2 1 NA 1 1 1 3 0 1 NA 0 1
实现代码
dplyr 实现(推荐)
通过行式计算直接剔除每行的NA后赋值,不需要写多分支条件判断:
library(dplyr) result <- input_df %>% rowwise() %>% mutate( valid_vals = list(na.omit(c_across(col1:col3))), out1 = valid_vals[[1]], out2 = valid_vals[[2]] ) %>% select(-valid_vals) %>% ungroup()
代码逻辑:
- 开启
rowwise()行式计算模式,后续操作逐行执行 - 用
c_across选取当前行的3个目标列值,通过na.omit剔除NA得到2个有效值,暂存在列表列中 - 分别取出暂存值的第一个、第二个元素赋值给新列
- 删除临时列表列,取消行式分组即可得到结果
base R 实现
不需要加载第三方包,直接用apply按行处理即可:
valid_mat <- t(apply(input_df[,1:3], 1, function(row) na.omit(row))) input_df$out1 <- valid_mat[,1] input_df$out2 <- valid_mat[,2]
两种方式运行后输出结果和预期完全一致。
注意:以上方案默认每行严格存在1个NA、2个有效值,如果数据存在NA数量不符合规则的行,建议提前做数据校验,避免结果报错或出现意外值。
内容的提问来源于stack exchange,提问作者dgetty
相关产品推荐
相关产品推荐

