使用 sapply 和 grepl 将向量与多个字符串匹配时添加标记
Adding tokens when matching a vector to multiple strings using sapply and grepl
我正在尝试检查包含许多元素的向量与包含字符串的数据框的列之间的匹配。
vec <- c("KIND", "Quest")
string <- ("lieberkind", "kind", "KIND", "Quest Nutrition", "Quest")
x <- sapply(vec, function (x) grepl(x, string, ignore.case = TRUE))
这是结果:
> x
KIND Quest
[1,] TRUE FALSE
[2,] TRUE FALSE
[3,] TRUE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
问题出在 "KIND" 的第一个结果中,它最终为 'lieberkind' 生成了 TRUE 值。
通常,我会添加一个标记来指定单词边界,例如:
grepl("\bKIND\b", string, ignore.case = TRUE)
[1] FALSE TRUE TRUE FALSE FALSE
但是当我使用 sapply
将向量的每个元素与字符串的每个元素进行比较时,我不知道该怎么做。
我显然不能这样做:
x <- sapply(vec, function (x) grepl(\bx\b, string, ignore.case = TRUE))
我该如何解决这个问题?
检查字边界的方法有多种,具体取决于您的数据。如果需要使用字边界,使用
x <- sapply(vec, function (x) grepl(paste0("\b",x,"\b"), string, ignore.case = TRUE))
或:
x <- sapply(vec, function (x) grepl(sprintf("\b%s\b", x), string, ignore.case = TRUE))
但是,如果您的 vec
包含内部带有特殊字符的条目(注意:不是在开头或结尾),那么您需要使用类似
的内容来转义它们
x <- sapply(vec, function (x) grepl(paste0("\b",gsub("([][/\\^$*+?.()|{}-])", "\\\1", x),"\b"), string, ignore.case = TRUE))
最后,如果您将单词边界定义为空白字符或 start/end 字符串,我宁愿推荐 PCRE 正则表达式,如
x <- sapply(vec, function (x) grepl(paste0("(?<!\S)",gsub("([][/\\^$*+?.()|{}-])", "\\\1", x),"(?!\S)"), string, ignore.case = TRUE, perl=TRUE))
使用您的测试数据的所有 3 个案例的结果如下所示:
KIND Quest
[1,] FALSE FALSE
[2,] TRUE FALSE
[3,] TRUE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
P.S。无论您使用 paste0
还是 sprintf
,您都会得到相同的结果。
我正在尝试检查包含许多元素的向量与包含字符串的数据框的列之间的匹配。
vec <- c("KIND", "Quest")
string <- ("lieberkind", "kind", "KIND", "Quest Nutrition", "Quest")
x <- sapply(vec, function (x) grepl(x, string, ignore.case = TRUE))
这是结果:
> x
KIND Quest
[1,] TRUE FALSE
[2,] TRUE FALSE
[3,] TRUE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
问题出在 "KIND" 的第一个结果中,它最终为 'lieberkind' 生成了 TRUE 值。
通常,我会添加一个标记来指定单词边界,例如:
grepl("\bKIND\b", string, ignore.case = TRUE)
[1] FALSE TRUE TRUE FALSE FALSE
但是当我使用 sapply
将向量的每个元素与字符串的每个元素进行比较时,我不知道该怎么做。
我显然不能这样做:
x <- sapply(vec, function (x) grepl(\bx\b, string, ignore.case = TRUE))
我该如何解决这个问题?
检查字边界的方法有多种,具体取决于您的数据。如果需要使用字边界,使用
x <- sapply(vec, function (x) grepl(paste0("\b",x,"\b"), string, ignore.case = TRUE))
或
x <- sapply(vec, function (x) grepl(sprintf("\b%s\b", x), string, ignore.case = TRUE))
但是,如果您的 vec
包含内部带有特殊字符的条目(注意:不是在开头或结尾),那么您需要使用类似
x <- sapply(vec, function (x) grepl(paste0("\b",gsub("([][/\\^$*+?.()|{}-])", "\\\1", x),"\b"), string, ignore.case = TRUE))
最后,如果您将单词边界定义为空白字符或 start/end 字符串,我宁愿推荐 PCRE 正则表达式,如
x <- sapply(vec, function (x) grepl(paste0("(?<!\S)",gsub("([][/\\^$*+?.()|{}-])", "\\\1", x),"(?!\S)"), string, ignore.case = TRUE, perl=TRUE))
使用您的测试数据的所有 3 个案例的结果如下所示:
KIND Quest
[1,] FALSE FALSE
[2,] TRUE FALSE
[3,] TRUE FALSE
[4,] FALSE TRUE
[5,] FALSE TRUE
P.S。无论您使用 paste0
还是 sprintf
,您都会得到相同的结果。