1

我正在使用agrepl()通过模糊匹配单词来过滤 data.table。这对我来说很好,使用这样的东西:

 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

显然,通过查看这个,您可以看到在这种情况下“setos”将与“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 species”,而不仅仅是“setosh”(作为匹配的部分)。

希望这更有帮助!

4

2 回答 2

0

如果我理解正确,您真的只想从 strings 中提取模糊匹配。听起来使用数据框执行此操作并返回向量也存在一些问题,但我认为一旦您成功提取了匹配的子字符串,它就会变得更加简单。

我将使用以下玩具数据:

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. 我们可以对datausing的每一列执行此操作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              
于 2019-07-13T08:04:10.563 回答
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

最终编辑:

我不确定使用 grepping 所有列的业务iris是关于什么的,但是要在 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,我们可以做 Stuff。我们可以删除 NA 并查看唯一值:

res <- res[ !is.na(res) ]
unique(res)

结果:

[1] "setosa" "setosh"

FINAL FINAL EDIT : 看来 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"
于 2019-07-12T11:45:30.920 回答