【问题标题】:String fuzzy matching in dataframe数据框中的字符串模糊匹配
【发布时间】:2018-04-08 06:33:21
【问题描述】:

我有一个包含文章标题和相关 url 链接的数据框。

我的问题是对应标题的那一行不需要url链接,例如:

               title                  |                     urls
    Who will be the next president?   | https://website/5-ways-to-make-a-cocktail.com 
    5 ways to make a cocktail         | https://website/who-will-be-the-next-president.com
    2 millions raised by this startup | https://website/how-did-you-find-your-house.com 
    How did you find your house       | https://website/2-millions-raised-by-this-startup.com
    How did you find your house       | https://washingtonpost/article/latest-movies-in-theater.com
    Latest movies in Theater          | www.newspaper/mynews/what-to-cook-in-summer.com
    What to cook in summer            | https://website/2-millions-raised-by-this-startup.com

我的猜测是我需要考虑如此模糊的匹配逻辑,但我不确定如何。对于重复项,我将只使用unique 函数。

我开始使用 RecordLinkage 包中的 levenshteinSim 函数,该函数为每一行提供相似度分数,但显然由于行不匹配,各处的相似度分数都很低。

我还从stringdist 包中听说了stringdistmatrix 函数,但不知道如何在这里使用它。

【问题讨论】:

  • 这种“website/[string].com”结构是否始终存在,或者这只是您的示例?如果是这样,您可以使用简单的正则表达式将其删除并进行完全匹配。
  • 嗨,是的,我知道正则表达式,但不,它变化很大,因为有很多不同的网站:/
  • 您可能应该让您的示例更具代表性,因为就目前而言,为您提供的示例提供解决方案非常容易。
  • @DavidArenburg 完全同意
  • 感谢反馈,我已编辑

标签: r fuzzy-logic stringdist record-linkage


【解决方案1】:

当然可以优化,但这可能会让你开始:

  1. 函数matcher() converts 比较两个字符串并产生一个分数
  2. 之后我们将尝试将标题与matcher() 进行匹配并获得最高分
  3. 如果无法找到高于阈值的分数,则返回 NA


R:
matcher <- function(needle, haystack) {
  ### Analyzes the url part, converts them to lower case words
  ### and calculates a score to return

  # convert url
  y <- unlist(strsplit(haystack, '/'))
  y <- tolower(unlist(strsplit(y[length(y)], '[-.]')))

  # convert needle
  x <- needle

  # sum it up
  (z <- (sum(x %in% y) / length(x) + sum(y %in% x) / length(y)) / 2)
}

pairer <- function(titles, urls, threshold = 0.75) {
  ### Calculates scores for each title -> url combination
  result <- vector(length = length(titles))
  for (i in seq_along(titles)) {
    needle <- tolower(unlist(strsplit(titles[i], ' ')))
    scores <- unlist(lapply(urls, function(url) matcher(needle, url)))
    high_score <- max(scores)

    # above threshold ?
    result[i] <- ifelse(high_score >= threshold, 
                        urls[which(scores == high_score)], NA)
  }
  return(result)
}

df$guess <- pairer(df$title, df$urls)
df

这会产生

                              title                                                        urls                                                       guess
1   Who will be the next president?               https://website/5-ways-to-make-a-cocktail.com          https://website/who-will-be-the-next-president.com
2         5 ways to make a cocktail          https://website/who-will-be-the-next-president.com               https://website/5-ways-to-make-a-cocktail.com
3 2 millions raised by this startup             https://website/how-did-you-find-your-house.com       https://website/2-millions-raised-by-this-startup.com
4       How did you find your house       https://website/2-millions-raised-by-this-startup.com             https://website/how-did-you-find-your-house.com
5       How did you find your house https://washingtonpost/article/latest-movies-in-theater.com             https://website/how-did-you-find-your-house.com
6          Latest movies in Theater             www.newspaper/mynews/what-to-cook-in-summer.com https://washingtonpost/article/latest-movies-in-theater.com
7            What to cook in summer       https://website/2-millions-raised-by-this-startup.com             www.newspaper/mynews/what-to-cook-in-summer.com
> 

【讨论】:

  • 嘿,抱歉我的回复太晚了!非常感谢 !我尝试了你的函数,但我得到的回报是“strsplit(dataf$url,“/”)中的错误:非字符参数”所以不确定我在那里缺少什么......
猜你喜欢
  • 2012-02-14
  • 2014-11-02
  • 2017-08-03
  • 2018-05-31
  • 2021-04-19
  • 1970-01-01
  • 2015-03-26
  • 2018-04-25
  • 1970-01-01
相关资源
最近更新 更多