这是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- >检查r1,p2->检查r2等)包含一个值。
“手动”解决方案
可以像下面这样使用很多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列中)...因此,按类型添加列(或可以转换为该结果)的解决方案将“用一只石头杀死两只鸟”。>
答案 0 :(得分:0)
这里是一种解决方案,其中我将类型列转换为矩阵,并使用awk
列中的信息对其进行更新,然后在其上应用搜索相关类型的次数为要查找的类型的次数。
awk
额外
使用r
可以执行以下操作。管道只是为了提高可读性,其中一些步骤可能可以简化。
# Convert to a matrix
pMAT <- DT[, as.matrix(.SD), .SDcols = patterns("^p")]
# Subset a matrix with another matrix of the r columns
pMAT[] <- pMAT[DT[, as.logical(as.matrix(.SD)), .SDcols = patterns("^r")]]
types2check <- c("type1", "type2")
for (t in types2check) {
set(
x = DT,
j = paste0(t, "_present"),
value = ifelse(apply(pMAT, 1, function(x) any(x == t, na.rm = TRUE)), "yes", "no")
)
}