从多个字符串的 grepl 匹配中返回匹配的字符串,而不是逻辑
Returning the matched string from a grepl match of multiple strings, rather than the logical
目前我正在使用带有 grepl 的嵌套 ifelse 函数来检查与数据框中字符串向量的匹配,例如:
# vector of possible words to match
x <- c("Action", "Adventure", "Animation")
# data
my_text <- c("This one has Animation.", "This has none.", "Here is Adventure.")
my_text <- as.data.frame(my_text)
my_text$new_column <- ifelse (
grepl("Action", my_text$my_text) == TRUE,
"Action",
ifelse (
grepl("Adventure", my_text$my_text) == TRUE,
"Adventure",
ifelse (
grepl("Animation", my_text$my_text) == TRUE,
"Animation", NA)))
> my_text$new_column
[1] "Animation" NA "Adventure"
这对少数元素(例如这里的三个)没问题,但是当可能的匹配项更大(例如 150)时,我如何 return?嵌套的 ifelse 看起来很疯狂。我知道我可以像下面的代码一样一次 grepl 多个东西,但是这个 return 是合乎逻辑的,只告诉我字符串是否匹配,而不是哪个匹配。我想知道匹配的是什么(如果是多个,任何匹配都可以。
x <- c("Action", "Adventure", "Animation")
my_text <- c("This one has Animation.", "This has none.", "Here is Adventure.")
grepl(paste(x, collapse = "|"), my_text)
returns: [1] TRUE FALSE TRUE
what i'd like it to return: "Animation" ""(or FALSE) "Adventure"
遵循模式 here,base
解决方案。
x <- c("ActionABC", "AdventureDEF", "AnimationGHI")
regmatches(x, regexpr("(Action|Adventure|Animation)", x))
stringr
有更简单的方法
library(stringr)
str_extract(x, "(Action|Adventure|Animation)")
这样就可以了...
my_text$new_column <- unlist(
apply(
sapply(x, grepl, my_text$my_text),
1,
function(y) paste("",x[y])))
sapply
生成一个逻辑矩阵,显示 x
项中的哪些项出现在列的每个元素中。然后 apply
逐行运行并将 x
对应于 TRUE
值的所有值粘贴在一起。 (它在开头粘贴了一个""
以避免NA
s并保持输出的长度与原始数据相同。)如果x
中的两个术语匹配一行, 它们将在输出中粘贴在一起。
基于 Benjamin 的基本解决方案,使用 lapply 以便在没有匹配项时您将拥有一个字符 (0) 值。
直接在你的示例代码上使用regmatches,会不会出现如下错误。
my_text$new_column <-regmatches(x = my_text$my_text, m = regexpr(pattern = paste(x, collapse = "|"), text = my_text$my_text))
Error in `$<-.data.frame`(`*tmp*`, new_column, value = c("Animation", :
replacement has 2 rows, data has 3
这是因为只有 2 个匹配项,它会尝试在具有 3 行的数据框列中匹配匹配值。
要用特殊值填充不匹配项以便可以直接完成此操作,我们可以使用 lapply.
my_text$new_column <-
lapply(X = my_text$my_text, FUN = function(X){
regmatches(x = X, m = regexpr(pattern = paste(x, collapse = "|"), text = X))
})
这会将字符 (0) 放在没有匹配项的地方。
Table screenshot
希望对您有所帮助。
目前我正在使用带有 grepl 的嵌套 ifelse 函数来检查与数据框中字符串向量的匹配,例如:
# vector of possible words to match
x <- c("Action", "Adventure", "Animation")
# data
my_text <- c("This one has Animation.", "This has none.", "Here is Adventure.")
my_text <- as.data.frame(my_text)
my_text$new_column <- ifelse (
grepl("Action", my_text$my_text) == TRUE,
"Action",
ifelse (
grepl("Adventure", my_text$my_text) == TRUE,
"Adventure",
ifelse (
grepl("Animation", my_text$my_text) == TRUE,
"Animation", NA)))
> my_text$new_column
[1] "Animation" NA "Adventure"
这对少数元素(例如这里的三个)没问题,但是当可能的匹配项更大(例如 150)时,我如何 return?嵌套的 ifelse 看起来很疯狂。我知道我可以像下面的代码一样一次 grepl 多个东西,但是这个 return 是合乎逻辑的,只告诉我字符串是否匹配,而不是哪个匹配。我想知道匹配的是什么(如果是多个,任何匹配都可以。
x <- c("Action", "Adventure", "Animation")
my_text <- c("This one has Animation.", "This has none.", "Here is Adventure.")
grepl(paste(x, collapse = "|"), my_text)
returns: [1] TRUE FALSE TRUE
what i'd like it to return: "Animation" ""(or FALSE) "Adventure"
遵循模式 here,base
解决方案。
x <- c("ActionABC", "AdventureDEF", "AnimationGHI")
regmatches(x, regexpr("(Action|Adventure|Animation)", x))
stringr
有更简单的方法
library(stringr)
str_extract(x, "(Action|Adventure|Animation)")
这样就可以了...
my_text$new_column <- unlist(
apply(
sapply(x, grepl, my_text$my_text),
1,
function(y) paste("",x[y])))
sapply
生成一个逻辑矩阵,显示 x
项中的哪些项出现在列的每个元素中。然后 apply
逐行运行并将 x
对应于 TRUE
值的所有值粘贴在一起。 (它在开头粘贴了一个""
以避免NA
s并保持输出的长度与原始数据相同。)如果x
中的两个术语匹配一行, 它们将在输出中粘贴在一起。
基于 Benjamin 的基本解决方案,使用 lapply 以便在没有匹配项时您将拥有一个字符 (0) 值。
直接在你的示例代码上使用regmatches,会不会出现如下错误。
my_text$new_column <-regmatches(x = my_text$my_text, m = regexpr(pattern = paste(x, collapse = "|"), text = my_text$my_text))
Error in `$<-.data.frame`(`*tmp*`, new_column, value = c("Animation", :
replacement has 2 rows, data has 3
这是因为只有 2 个匹配项,它会尝试在具有 3 行的数据框列中匹配匹配值。
要用特殊值填充不匹配项以便可以直接完成此操作,我们可以使用 lapply.
my_text$new_column <-
lapply(X = my_text$my_text, FUN = function(X){
regmatches(x = X, m = regexpr(pattern = paste(x, collapse = "|"), text = X))
})
这会将字符 (0) 放在没有匹配项的地方。
Table screenshot
希望对您有所帮助。