r - 根据其他列中的最小值查找列值和名称
问题描述
我有一个看起来像这样的 data.table
library( data.table )
dt <- data.table( p1 = c("a", "b", "c", "d", "e", "f", "g"),
p2 = c("b", "c", "d", "a", "f", "g", "h"),
p3 = c("z", "x", NA, NA, "y", NA, "s"),
t1 = c(1, 2, 3, NA, 5, 6, 7),
t2 = c(7, 6, 5, NA, 3, 2, NA),
t3 = c(8, 3, NA, NA, 2, NA, 1) )
# p1 p2 p3 t1 t2 t3
# 1: a b z 1 7 8
# 2: b c x 2 6 3
# 3: c d <NA> 3 5 NA
# 4: d a <NA> NA NA NA
# 5: e f y 5 3 2
# 6: f g <NA> 6 2 NA
# 7: g h s 7 NA 1
它具有代表名称的 p 列和代表值的 t 列。t1 是对应于 p1 的值,t2 对应于 p2 等。
在每一行上,p 列的值是唯一的(或NA
)。t 列中的值也是如此。
我想要做的是创建三个新列:
t_min
,每行所有 t 列的最小值(不包括 NA)p_min
,如果t_min存在(不是NA),p列的对应值... 所以如果t2-column有t-min值,column对应的值p2
。p_col_min
, 列的名称,如果是 p_min,则为值。因此,如果 p_min 值来自 colum ,则为p2
“p2”。
我更喜欢 a data.table
,因为我的实际数据包含更多的行和列。我知道熔化是一种选择,但我想用这些数据来保存我的内存,所以使用的内存越少越好(生产数据包含几百万行和 >200 列)。
到目前为止,我已经找到了一种t_min
使用以下方法创建 -column 的方法:
t_cols = dt[ , .SD, .SDcols = grep( "t[1-3]", names( dt ), value = TRUE ) ]
dt[ !all( is.na( t_cols ) ),
t_min := do.call( pmin, c( .SD, list( na.rm = TRUE ) ) ),
.SDcols = names( t_cols ) ]
但我无法全神贯注地创建p_min
和p_col_min
列。我想which.min()
在某个地方发挥作用,但我无法弄清楚。可能我忽略了一些简单的事情(它似乎总是.. ;-))。
期望的输出
dt.desired <- data.table( p1 = c("a", "b", "c", "d", "e", "f", "g"),
p2 = c("b", "c", "d", "a", "f", "g", "h"),
p3 = c("z", "x", NA, NA, "y", NA, "s"),
t1 = c(1, 2, 3, NA, 5, 6, 7),
t2 = c(7, 6, 5, NA, 3, 2, NA),
t3 = c(8, 3, NA, NA, 2, NA, 1),
t_min = c(1,2,3,NA,2,2,1),
p_min = c("a","b","c",NA,"y","g","s"),
p_col_min = c("p1","p1","p1",NA,"p3","p2","p3") )
# p1 p2 p3 t1 t2 t3 t_min p_min p_col_min
# 1: a b z 1 7 8 1 a p1
# 2: b c x 2 6 3 2 b p1
# 3: c d <NA> 3 5 NA 3 c p1
# 4: d a <NA> NA NA NA NA <NA> <NA>
# 5: e f y 5 3 2 2 y p3
# 6: f g <NA> 6 2 NA 2 g p2
# 7: g h s 7 NA 1 1 s p3
解决方案
这是另一条路线:
dt[, t_min := do.call(pmin, c(.SD, na.rm = TRUE)), .SDcols = patterns('t[[:digit:]]')]
dt[!is.na(t_min),
c('p_min', 'p_min_col') := {
arr_ind = .SD[, which(t_min == .SD, arr.ind = TRUE), .SDcols = patterns('t[[:digit:]]')]
arr_ind = arr_ind[order(arr_ind[, 1]), ]
p_m = .SD[, as.matrix(.SD)[arr_ind], .SDcols = patterns('p')]
p_m_c = grep('^p', names(.SD), value = TRUE)[arr_ind[, 2]]
list(p_m, p_m_c)
}
]
推荐阅读
- sql - 在第一个分组记录上失败的日期逻辑之间的差距检测
- python - Python - if 语句中的或运算符的链接不提供预期的结果
- laravel - Laravel Maat网站excel
- amazon-web-services - Lambda 函数的 AWS 安全组规则
- r - 如何在数据框中选择两个所需的列来构建 svm 模型?
- android - 在 Volley 中传递 Edittext 值以获取请求 URL
- c# - 显式流上传文件到谷歌驱动器
- php - php到mysql数据检索
- ios - 函数在签入 if 语句 Swift 后跳转 else 语句
- asp.net - 无法检索“DataSet1”数据集的数据