我需要计算 a 的某些列的每一行的“最佳值”data.table
。每行的最佳值是按选定列的给定顺序排列的第一个非 NA 列的值。
根据要求,要包含的列可能会因顺序或数量而异。此外,应为每行存储提供最佳值的列的名称。
示例数据
With
library(data.table)
library(magrittr)
n <- 7
set.seed(1234)
dt <- sample.int(100, n*5, replace = TRUE) %>%
ifelse(. < 35, NA, .) %>%
matrix(, nrow = n) %>%
as.data.table()
例子data.table
is
V1 V2 V3 V4 V5
1: NA NA NA NA 84
2: 63 67 84 NA NA
3: 61 52 NA NA 46
4: 63 70 NA NA NA
5: 87 55 NA 82 NA
6: 65 NA NA 53 51
7: NA 93 NA 92 NA
要包含在给定顺序中的列是
selected_cols <- c("V3", "V4", "V1")
硬编码嵌套的预期结果ifelse
硬编码版本
dt[, best_value := ifelse(!is.na(V3), V3, ifelse(!is.na(V4), V4, V1))]
将给出最佳价值的预期结果
V1 V2 V3 V4 V5 best_value
1: NA NA NA NA 84 NA
2: 63 67 84 NA NA 84
3: 61 52 NA NA 46 61
4: 63 70 NA NA NA 63
5: 87 55 NA 82 NA 82
6: 65 NA NA 53 51 53
7: NA 93 NA 92 NA 92
但它仍然没有显示从哪一列中获取了最佳值。
在第 2 行列V3
已经具有非 NA 值。对于第 5、6 和 7 行,列中的值V4
被采取。最后,专栏V1
给出第 3 行和第 4 行的值,其中V3
and V4
不适用。第 1 行包含 NA,因为所考虑的所有列都是 NA。
灵活的方法for
loop
Using a for
循环选定的列和一些data.table
特征
dt[, best_value := NA_integer_]
dt[, best_col := NA_character_]
for (x in selected_cols) {
dt[is.na(best_value), best_col := ifelse(!is.na(.SD), names(.SD), NA), .SDcols = x]
dt[is.na(best_value), best_value:= .SD, .SDcols = x]
}
我们得到了完整的预期结果
V1 V2 V3 V4 V5 best_value best_col
1: NA NA NA NA 84 NA NA
2: 63 67 84 NA NA 84 V3
3: 61 52 NA NA 46 61 V1
4: 63 70 NA NA NA 63 V1
5: 87 55 NA 82 NA 82 V4
6: 65 NA NA 53 51 53 V4
7: NA 93 NA 92 NA 92 V4
此外,可以轻松更改要包含的列向量。
Question
然而,该方法具有for
有两个语句的循环对我来说看起来相当笨拙,而且不是很data.table
-like.
有没有更好的方法来实现这些结果data.table
or dplyr
甚至在基础 R 中?