基于具有m个字符串列的data.table DT,如何标记至少一个列中出现字符串的行(例如,“ BlaBla”)?
我想要的是:
DT[, flag_BlaBLa:=(test if "BlaBLa" appears in any column except the first one)]
我不想明确引用列名。相反,我需要将col 2引用为DT中的最大col编号(也许:2:ncol(DT)
)。为什么不?实际上,我有一个data.frames列表,每个列表中的列数都不同。如上所述,我需要为列表中的所有data.frames创建标记。
Edit1:添加一个可复制的示例。 Edit2:将某些“ BlaBLa”字符串更改为“ BlaBLa + something”。还应将此匹配项视为匹配项,因为它们包括“ BlaBLa”。
DT以cols a,b,c
开头,我想要一个脚本来创建flag_BlaBLa
。最终结果将是:
DT <- data.table(a=c("x","y","z",'w'),
b=c('BlaBLa','BLe','Bli','BlaBLaSometing'),
c=c('Bla','BLe','BlaBLa','Blo'),
flag_BlaBLa=c(T,F,T,T)
)
对于列表,最终结果应为:
DT1 <- data.table(a=c("x","y","z",'w'),
b=c('BlaBLa','BLe','Bli','BlaBLaSomething'),
c=c('Bla','BLe','BlaBLa','Blo'),
flag_BlaBLa=c(T,F,T,T)
)
DT2 <- data.table(a=c("q","j","p"),
b=c('BLe','Bli','BlaBLa'),
flag_BlaBLa=c(F,F,T)
)
l <- list(DT1,DT2)
答案 0 :(得分:3)
我们可以在.SDcols
中指定感兴趣的列,遍历data.table(.SD
)的子集,检查它是否等于'BlaBLa',Reduce
使其成为单个逻辑vector
创建列
library(data.table)
lapply(l, function(x) x[, flag_BlaBLa := Reduce(`|`, lapply(.SD, `==`,
"BlaBLa")), .SDcols = 2:ncol(x)][])
#[[1]]
# a b c flag_BlaBLa
#1: x BlaBLa Bla TRUE
#2: y BLe BLe FALSE
#3: z Bli BlaBLa TRUE
#4: w BlaBLa Blo TRUE
#[[2]]
# a b flag_BlaBLa
#1: q BLe FALSE
#2: j Bli FALSE
#3: p BlaBLa TRUE
答案 1 :(得分:1)
我们可以遍历列表,选择列,然后检查任何一行中是否至少有一个“ BlaBLa”并标记行TRUE
/ FALSE
。
library(data.table)
lapply(l, function(x) x[, flag_BlaBLa := rowSums(x[,2:ncol(x)] == "BlaBLa") > 0])
l
#[[1]]
# a b c flag_BlaBLa
#1: x BlaBLa Bla TRUE
#2: y BLe BLe FALSE
#3: z Bli BlaBLa TRUE
#4: w BlaBLa Blo TRUE
#[[2]]
# a b flag_BlaBLa
#1: q BLe FALSE
#2: j Bli FALSE
#3: p BlaBLa TRUE
编辑
如果这不是完全匹配,并且我们需要找到该字符串的模式,那么在使用rowSums
lapply(l, function(x) x[, flag_BlaBLa := rowSums(sapply(x[, 2:ncol(x)],
grepl, pattern = 'BlaBLa', fixed = TRUE)) > 0])
#[[1]]
# a b c flag_BlaBLa
#1: x BlaBLa Bla TRUE
#2: y BLe BLe FALSE
#3: z Bli BlaBLa TRUE
#4: w BlaBLaSomething Blo TRUE
#[[2]]
# a b flag_BlaBLa
#1: q BLe FALSE
#2: j Bli FALSE
#3: p BlaBLa TRUE
答案 2 :(得分:1)
这是使用.SDcols
require(dplyr)
require(data.table)
require(stringr)
DT <- DT[, key_ := do.call(paste, c(.SD, sep = "_")), .SDcols = 2:ncol(DT)]
DT <- DT[, has_blabla := as.integer(str_detect(key_, "BlaBla"))]
第一个创建键,每行所有列值均以'_'分隔。然后,下一个对其进行搜索并将其标记为二进制。搜索返回TRUE
或FALSE
,将其强制为整数时为二进制。
答案 3 :(得分:1)
我将在列表上使用for
循环,在列上使用sapply
,并使用.SDcols
排除第一个:
for (ii in seq_along(l)) {
l[[ii]][ , .SDcols = -1L,
flag_BlaBLa := any(sapply(.SD, grepl, pattern = 'BlaBLa', fixed = TRUE))]
}
请注意,由于您实际上并未使用任何正则表达式,因此fixed = TRUE
是使用grepl
的更有效的选择。如果您要检测的模式确实是正则表达式,请删除fixed = TRUE
。
如果不是所有的列都是字符串列,则可以通过使.SDcols
更严格(例如
.SDcols = intersect(2:ncols(l[[ii]]), which(sapply(l[[ii]], is.character)))
(或可能使用is.character(x) || is.factor(x)
)