R data.table如何忽略NA值合并多列为单列(类dplyr::coalesce)
问题场景
现有如下data.table对象,需要将title、sha两列拼接为新列,拼接时自动排除存在的NA缺失值:
library(data.table) dt <- data.table("title"=c("A", "B", NA, "D"), "sha"=c("1", NA, "3", NA), "date" = c("1/1/2020","1/2/2020","1/3/2020","1/4/2020$"))
期望生成的新列结果如下:
new A1 B 3 D
要求基于原生data.table语法实现,同时需要找到类似dplyr::coalesce功能的原生实现方案。
实现方法
高性能向量写法(适配当前两列场景)
直接用data.table内置的向量判断函数fifelse分支处理,全程向量运算无行级循环,千万行级数据也能秒出结果:
dt[, new := fifelse( is.na(title), sha, fifelse(is.na(sha), title, paste0(title, sha)) )]
通用多列写法
如果需要合并的列数较多,可以用按行处理的通用写法,自动跳过指定列里的所有NA值后拼接:
# 指定需要合并的列 cols_to_merge <- c("title", "sha") dt[, new := apply(.SD, 1, \(x) paste0(na.omit(x), collapse = "")), .SDcols = cols_to_merge]
类coalesce功能的原生实现
如果不需要拼接多列非空值,只需要取多列中第一个出现的非空值,直接用data.table内置的fcoalesce即可,功能和dplyr::coalesce完全一致,性能更高:
# 注意:该写法仅取首个非空值,不会拼接两个非空值,仅作coalesce功能参考 dt[, new_coalesce := fcoalesce(title, sha)]
运行上述拼接代码后,得到的结果完全匹配预期:
> dt title sha date new 1: A 1 1/1/2020 A1 2: B <NA> 1/2/2020 B 3: <NA> 3 1/3/2020 3 4: D <NA> 1/4/2020 D
说明
fcoalesce是data.table原生提供的高性能多向量取首个非空值函数,支持任意多向量输入,处理大数据集时速度远高于dplyr版本的coalesce。- 两列拼接场景优先用
fifelse的向量写法,避免行级循环带来的性能损耗;列数较多时再用apply的通用写法简化代码。
内容的提问来源于stack exchange,提问作者Zach Fara
相关产品推荐
相关产品推荐

