r - 替换 data.table 中的嵌套 ifelse
问题描述
我想在我的列中创建一个列,它从一组给定的列data.table
中获取第一个非NA
值:
library(data.table)
o <- data.table(a1 = c(1, NA, NA, NA),
a2 = c(NA, 2, NA, NA),
a3 = c(NA, NA, 3, NA),
default = 11:14)
res <- copy(o)
res[, nc := ifelse(!is.na(a1),
a1,
ifelse(!is.na(a2),
a2,
ifelse(!is.na(a3),
a3,
default)))][]
# a1 a2 a3 default nc
# 1: 1 NA NA 11 1
# 2: NA 2 NA 12 2
# 3: NA NA 3 13 3
# 4: NA NA NA 14 14
由于有很多列,这变得相当乏味,我想用某种循环来替换它。我已经阅读了Shorten nested ifelse并且至少可以通过以下方式获得第一个非NA
列的位置max.col
:
(col_ind <- o[, max.col(!sapply(.SD, is.na), "first"), .SDcol = patterns("^a|^default")])
# [1] 1 2 3 4
我现在如何将列位置“映射”到列?使用矩阵子集,我可以做类似的事情, o[cbind(1:NROW(o), col_ind)]
但这由于明显的原因不起作用?max.col
任何人都知道如何解决这个问题(如果有一个惯用的解决方案,就不需要坚持这种方法data.table
?
解决方案
一些原始的想法:
1)使用fcase()
, (目前在开发版本中可用):
o[, nc := fcase(
!is.na(a1), a1,
!is.na(a2), a2,
!is.na(a3), a3,
rep(TRUE, nrow(o)), as.double(default)
)]
2)使用apply()
:
o[,
nc := apply(.SD, 1L, function(x) x[!is.na(x)][1L]),
.SDcol = patterns("^a|^default")]
3)使用melt()
:
o[, row := .I]
o[, nc := o[, melt(.SD, id.vars = "row"), .SDcol = patterns("^a|^default|^row")
][!is.na(value), value[1L], by = row]$V1]
o[, row := NULL]
4)set()
与您的col_ind
矢量一起使用:
for (i in seq_len(nrow(o))) set(o, i, "nc", value = o[[col_ind[i]]][i])
5) 使用max.col()
矩阵数字索引:
o[, nc := {
m <- as.matrix(.SD)
m[cbind(seq.int(.N), max.col(!is.na(m), "first"))]
}]
6)使用fcoalesce()
:
o[, names(o) := lapply(.SD, as.integer)][,
nc := fcoalesce(.SD)]
- 将 5 和 6 归功于 chinsoon12。
推荐阅读
- python - 尝试在 Python 中使用 PySimpleGUI 通过 openpyxl 读取 excel 单元格
- model - 如何从持久存储构建域模型?#DDD
- python - 我刚刚开始学习使用 selenium 进行网络抓取。我需要登录本地网站并双击某些项目
- java - Java 尝试使用 For 循环遍历 Int ArrayList 并添加到 Hashset 问题
- html - 如何在 CSS 中设置 li、span 和 a 元素的样式
- hadoop - HDP sanbox:yum install 抛出 403 错误
- javascript - 如何使用选项填充动态创建的选择
- python - Mrjob 无法在 dataproc 上创建集群:__init__() 有一个意外的关键字参数“通道”
- python - 如何将用户从登录页面重定向到不同应用程序 Django 中的注册页面?
- php - wordpress 插件意外字符