带有模糊匹配的单词的返回向量

时间:2019-07-12 11:02:33

标签: r agrep

我正在使用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.table上复制它。

例如,如果我更改值以使这一点更容易...

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”(作为匹配的部分)。

希望有帮助!

2 个答案:

答案 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中来提取匹配项。我们可以使用datalapply的每一列执行此操作:

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