【发布时间】:2019-07-24 05:23:27
【问题描述】:
这是来自Efficient way to subset data.table based on value in any of selected columns 的后续问题。
样本数据
我有一个带有 5 个 p 列的 data.table,表示一个类型(type1 或 type2 或NA)。
我还有 5 个 r 列,表示分数(1-10,或NA)。
library(data.table)
set.seed(123)
v <- c( "type1", "type2", NA_character_ )
v2 <- c( 1:10, rep( NA_integer_, 10 ) )
DT <- data.table( id = 1:100,
p1 = sample(v, 100, replace = TRUE ),
p2 = sample(v, 100, replace = TRUE ),
p3 = sample(v, 100, replace = TRUE ),
p4 = sample(v, 100, replace = TRUE ),
p5 = sample(v, 100, replace = TRUE ),
r1 = sample(v2, 100, replace = TRUE ),
r2 = sample(v2, 100, replace = TRUE ),
r3 = sample(v2, 100, replace = TRUE ),
r4 = sample(v2, 100, replace = TRUE ),
r5 = sample(v2, 100, replace = TRUE ))
期望的输出
我想创建两个新列(一个用于 type1,一个用于 type2),我逐行检查一个或多个 p 列中是否出现 type1/type2,以及是否至少有一个对应的 r 列(p1 - > check r1, p2 -> check r2, etc.) 包含一个值。
“手动”解决方案
这可以像下面这样使用大量的 AND 和 OR 语句来完成:
manual_solution <- DT[ ( p1 == "type1" & !is.na( r1 ) ) |
( p2 == "type1" & !is.na( r2 ) ) |
( p3 == "type1" & !is.na( r3 ) ) |
( p4 == "type1" & !is.na( r4 ) ) |
( p5 == "type1" & !is.na( r5 ) ),
type1_present := "yes"]
manual_solution <- DT[ ( p1 == "type2" & !is.na( r1 ) ) |
( p2 == "type2" & !is.na( r2 ) ) |
( p3 == "type2" & !is.na( r3 ) ) |
( p4 == "type2" & !is.na( r4 ) ) |
( p5 == "type2" & !is.na( r5 ) ),
type2_present := "yes"]
manual_solution[ is.na( type1_present ), type1_present := "no" ]
manual_solution[ is.na( type2_present ), type2_present := "no" ]
问题:数十个 p 和 r 列的自动化
但看看Efficient way to subset data.table based on value in any of selected columns 的答案,我相信有更好的方法。特别是因为我的生产数据包含更多的 p 列和 r 列。
所以我开始玩,但很快就卡住了......
#build vectors p-columns and r-columns
p_cols <- grep( "^p", names( DT ), value = TRUE )
r_cols <- grep( "^r", names( DT ), value = TRUE )
#create logical vectors to test for NA
logi_p <- as.data.table( sapply( DT[, ..p_cols ], function(x) !is.na(x) ) )
logi_r <- as.data.table( sapply( DT[, ..r_cols ], function(x) !is.na(x) ) )
#which non-NA p-values also have a non-NA r-value?
logi <- as.data.table( sapply( logi_p * logi_r, as.logical ) )
现在我没有任何关于如何继续的灵感。
有什么想法/建议吗?
奖金
我的主要关注点是上面的问题。但是我的生产数据还包含更多类型(在 p 列中)......因此,按类型添加列(或可以对该结果进行 dcast)的解决方案将“用一块石头杀死两只鸟”。
【问题讨论】:
-
我确信有一些技巧可以在宽格式中执行此操作,但我倾向于认为处理长格式数据更容易。像这样的东西似乎有效:
d <- melt(DT, id = "id", measure = patterns("^p", "^r"), value.name = c("p", "r"));d[ , `:=`(t1 = p == "type1" & !is.na(r), t2 = p == "type2" & !is.na(r))];d[ , .(type1_present = c("no", "yes")[any(t1, na.rm = TRUE) + 1], type2_present = c("no", "yes")[any(t2, na.rm = TRUE) + 1]), by = .(id)]. -
你可能会发现this question很有用
标签: r data.table