我正在使用agrepl()
通过模糊匹配单词来过滤数据表。使用以下命令对我来说工作正常:
library(data.table)
data <- as.data.table(iris)
pattern <- "setosh"
dt <- data[, lapply(.SD, function(x) agrepl(paste0("\\b(", pattern, ")\\b"), x, fixed = FALSE, ignore.case = TRUE))]
data<- data[rowSums(dt) > 0]
head(data)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1: 5.1 3.5 1.4 0.2 setosa
2: 4.9 3.0 1.4 0.2 setosa
3: 4.7 3.2 1.3 0.2 setosa
4: 4.6 3.1 1.5 0.2 setosa
5: 5.0 3.6 1.4 0.2 setosa
6: 5.4 3.9 1.7 0.4 setosa
很显然,通过查看此内容,您可以看到在这种情况下,“ setosh”将与“ setosa”进行模糊匹配。我想要的是获得与“ setosh”匹配的单词向量。因此,尽管在此示例中不相关,但如果它包含“ seposh”之类的其他类别,那么该类别也将匹配,因此您将拥有一个c("setosa", "seposh")
的向量。
编辑:
感谢下面的答案-我可以看到仅在查看向量时如何隔离发生模糊匹配的值,但是我的问题是:
例如,如果我更改值以使这一点更容易...
data <- as.data.table(iris)
data[Species == "versicolor", Species := "setosh species"] # changing a value so it would match
pattern <- "setosh"
dt <- data[, lapply(.SD, function(x) agrep(paste0("\\b(", pattern, ")\\b"), x, value = TRUE, fixed = FALSE, ignore.case = TRUE))]
Warning messages:
1: In as.data.table.list(jval) :
Item 1 is of size 0 but maximum size is 100, therefore recycled with 'NA'
2: In as.data.table.list(jval) :
Item 2 is of size 0 but maximum size is 100, therefore recycled with 'NA'
3: In as.data.table.list(jval) :
Item 3 is of size 0 but maximum size is 100, therefore recycled with 'NA'
4: In as.data.table.list(jval) :
Item 4 is of size 0 but maximum size is 100, therefore recycled with 'NA'
unique(dt)
Species
1: setosa
2: setosh species
您可以看到我没有向量中的结果,并且结果包括完整值“ setosh种”,而不仅仅是“ setosh”(作为匹配的部分)。
希望有帮助!
答案 0 :(得分:0)
只需将agrep
的输出用作您要抓取的字符向量的索引。
vec <- c("setosh", "setosz", "sethosz", "etosh", "ethos", "seosh")
idx <- agrep("setosh", vec) # grepl works as well
vec[idx]
结果:
[1] "setosh" "setosz" "etosh" "seosh"
编辑:好,但是如果结果只需要匹配的字符串怎么办?不是全部,而是匹配的部分?然后我们会觉得很有趣,因为grep / grepl和agrep / agrepl不能那样工作。幸运的是,这里有aregexec
函数。
vec <- c("setosh is my name", "setosz", "sethosz who",
"what etosh", "ethos", "seosh", "funk setos brother")
matches <- aregexec("setosh", vec)
matches
现在包含一个列表,其中vec
的每个元素都有一个元素。该列表的每个元素都包含一个数字-比赛开始-具有属性match.length
:
> matches[[1]]
[1] 1
attr(,"match.length")
[1] 6
我们可以使用这些数字来提取匹配的字符串。
library(purrr)
starts <- unlist(matches)
ends <- starts - 1 + map_int(matches, ~ attr(., "match.length"))
res <- substr(vec, starts, ends)
res[ starts < 0 ] <- NA
最终编辑:
我不确定将g iris
的所有列都用grep处理,但是要在Species列中获取匹配的子字符串向量,我将执行以下操作:
vec <- data$Species
matches <- aregexec("setosh", vec)
starts <- unlist(matches)
ends <- starts - 1 + map_int(matches, ~ attr(., "match.length"))
res <- substr(vec, starts, ends)
res[ starts < 0 ] <- NA
有了res,我们就可以做东西。我们可以删除NA并查看唯一值:
res <- res[ !is.na(res) ]
unique(res)
结果:
[1] "setosa" "setosh"
最终编辑:看来OP所选择的示例与他们的想法并不完全相同。因此,我们将举另一个例子。
vec <- c("setosh is my name", "setosz", "sethosz who",
"what etosh", "ethos", "seosh", "funk setos brother")
data <- data.table(matrix(sample(vec, 100, replace=T), ncol=5))
data
现在是一个data.table,在每一列中都有许多要匹配的东西。如果我们只想知道存在哪些匹配项,而又不需要知道在哪些列和行中找到了这些匹配项,并且我们想搜索所有列,则不需要将其作为二维对象。最好将其设为向量:
vec <- unlist(data)
好的,但是如果您想要获得唯一的 匹配项,我们可以进一步简化它:
vec <- unique(vec)
现在我们有了一个字符向量。如果您现在使用aregexec
查找匹配项并如上所述提取匹配项,您将得到一个字符向量
输出将是:
[1] "setosh" "setosz" "setos " "seosh" " etosh"
答案 1 :(得分:0)
如果我对您的理解正确,那么您真的只想从字符串中提取模糊匹配项。听起来好像对数据框执行此操作并返回向量还存在一些问题,但是我认为,一旦成功提取匹配的子字符串,它将变得更加简单。
我将使用以下玩具数据:
library(data.table)
set.seed(123)
data <-
as.data.table(matrix(sample(c("setosa", "blah seposa", "blah setosh blah",
"bleh versicolor", "bluh s", "bloh"),
15, T),
ncol = 3))
哪个返回此数据表。
V1 V2 V3
1: blah setosh blah bloh bloh
2: bloh blah setosh blah setosa
3: blah setosh blah bluh sep blah seposa
4: blah seposa bleh versicolor blah setosh blah
5: blah seposa bloh bluh sep
一月已经指出,您可以使用aregexec
来获取字符串中模糊匹配的位置。您可以通过将aregexec
的输出传递到regmatches
中来提取匹配项。我们可以使用data
对lapply
的每一列执行此操作:
data[, lapply(.SD, function(colu) {
regmatches(colu, aregexec("setosh", colu, max.distance = 2))
})]
这将返回一个data.table,每个单元格包含提取的模糊匹配子字符串,如果不匹配,则为空字符串。根据您从真实数据中获得的结果,您可能需要调整max.distance
来调整匹配的模糊性:
V1 V2 V3
1: setosh
2: setosh setosa
3: setosh seposa
4: seposa setosh
5: seposa