似乎很容易,但......好吧......
给定正则表达式的命名向量和数据表,如下所示:
library(data.table)
regexes <- c(a="^A$")
dt <- fread("
a,A,1
a,B,1
b,A,1
")
输入数据表是
dt
# V1 V2 V3
# 1: a A 1
# 2: a B 1
# 3: b A 1
regexes
中第一个元素的目标是:
如果V1=="a"
设置V3:=2
。除V2
与相应的正则表达式^A$
匹配,然后V3:=3
时。
(a
为names(regexes)[1]
,^A$
为regexes[1]
,2
和3
仅用于演示目的。我还有更多名字和循环的正则表达式,数据集大约是300.000行。)
所以预期输出是
# V1 V2 V3
# 1: a A 3 (*)
# 2: a B 2 (**)
# 3: b A 1
(*)3
因为V1
为a
且V2
(A
)与正则表达式匹配,
(**)2
因为V1
是a
而V2
(B
)与^A$
不匹配。
我尝试循环遍历正则表达式并通过这样管道子集:
for (x in seq(regexes))
dt[V1==names(regexes)[x], V3:=2][grepl(regexes[x], V2), V3:=3]
然而......
dt
# V1 V2 V3
# 1: a A 3
# 2: a B 2
# 3: b A 3 <- wrong, should remain 2
...它无法按预期工作,grepl
使用完整的V2
列,而不仅仅是V1=="a"
子集。我也尝试过其他一些有用的东西,但是花了太长时间(即不是使用data.table的方式)。
问题:什么是最好的数据表方式?我使用packageVersion("data.table")
‘1.9.7’
。
请注意,我可以使用数据框路线,例如像这样
df <- as.data.frame(dt)
for (x in seq(regexes)) {
idx <- df$V1==names(regexes)[x]
df$V3[idx] <- 2
df$V3[idx][grepl(regexes[x], df$V2[idx])] <- 3 # or ifelse()
}
但是 - 当然 - 我不希望将data.table转换为data.frame,然后在可能的情况下返回data.table。
提前致谢!
答案 0 :(得分:3)
...它无法按预期运行,
grepl
使用完整的V2
列,而不仅仅是V1=="a"
子集。
我会使用stringi,它允许简单地矢量化正则表达式测试:
library(stringi)
dt[V1 %in% names(regexes),
V3 := V3 + 1L + stri_detect(V2, regex = regexes[V1])
]
V1 V2 V3
1: a A 3
2: a B 2
3: b A 1
stri_detect
系列函数类似于基础的grepl
。