【问题标题】:Comparing two columns of two dataframes based on partial string match基于部分字符串匹配比较两个数据帧的两列
【发布时间】:2021-01-16 11:36:37
【问题描述】:

我有两个示例数据框,df1df2,如下所示。 df1 拥有选定的网球比赛装置列表,其中包含球员姓名(player1_name,player_name2)和比赛日期。此处使用玩家全名。

df2 拥有每个日期的所有网球比赛结果列表(winnerloser)。在这里,使用名字的第一个字母和完整的姓氏。 固定装置和结果的球员姓名是从不同的网站上抓取的。因此,在某些情况下,姓氏可能不完全匹配。 考虑到这一点,我想在df1 中添加一个新列,说明 player1 或 player2 是否赢了。基本上,我想通过给定相同日期的某些部分匹配方式,将df1 中的player1_nameplayer2_name 映射到df2 的赢家和输家。

dput(df1)
structure(list(date = structure(c(18534, 18534, 18534, 18534, 
18534, 18534, 18534), class = "Date"), player1_name = c("Laslo Djere", 
"Hugo Dellien", "Quentin Halys", "Steve Johnson", "Henri Laaksonen", 
"Thiago Monteiro", "Andrej Martin"), player2_name = c("Kevin Anderson", 
"Ricardas Berankis", "Marcos Giron", "Roberto Carballes", "Pablo Cuevas", 
"Nikoloz Basilashvili", "Joao Sousa")), row.names = c(NA, -7L
), class = "data.frame")
dput(df2)
structure(list(date = structure(c(18534, 18534, 18534, 18534, 
18534, 18534, 18534, 18534, 18534, 18534, 18534, 18534, 18534, 
18534, 18534, 18534, 18534, 18534, 18534, 18534), class = "Date"), 
    winner = c("L Harris", "M Berrettini", "M Polmans", "C Garin", 
    "A Davidovich Fokina", "D Lajovic", "K Anderson", "R Berankis", 
    "M Giron", "A Rublev", "N Djokovic", "R Carballes Baena", 
    "A Balazs", "P Cuevas", "T Monteiro", "S Tsitsipas", "D Shapovalov", 
    "G Dimitrov", "R Bautista Agut", "A Martin"), loser = c("A Popyrin", 
    "V Pospisil", "U Humbert", "P Kohlschreiber", "H Mayot", 
    "G Mager", "L Djere", "H Dellien", "Q Halys", "S Querrey", 
    "M Ymer", "S Johnson", "Y Uchiyama", "H Laaksonen", "N Basilashvili", 
    "J Munar", "G Simon", "G Barrere", "R Gasquet", "J Sousa"
    )), row.names = c(NA, -20L), class = "data.frame")

我创建了一个自定义函数,它可以使用 RecordLinkage 包将字符串与字符串向量中最接近的匹配项进行匹配。我可以使用这个函数编写一个效率极低的代码,但在去那里之前,我想看看我是否能以更有效的方式做到这一点。

ClosestMatch <- function(string, stringVector,max_threshold=0.5) {
        df<- character()
        for (i in 1:length(string)) {
                distance <- levenshteinSim(string[i], stringVector)
                if (max(distance)>=max_threshold) {
                        df[i]<- stringVector[which.max(distance)]
                }
                else {
                        df[i]= NA
                }
        }  
        return(df)
}

【问题讨论】:

  • 查看?adist

标签: r tidyverse fuzzy-comparison data-wrangling fuzzyjoin


【解决方案1】:

我尝试使用stringdist

library(stringdist)

for (i in 1:nrow(df1)) {
  
  #this first part combines the names of player1 and player2
  #and finds the closest match to the player combinations in df2

  d <-
    stringdist(
      paste(df1$player1_name[i], df1$player2_name[i]),
      paste(df2$winner, df2$loser),
            method = "cosine")
  #I like using the cosine method as it returns a decimal as opposed to an integer


  #then, added winner and loser columns to df1 based on which row in df2 had the closest match
  #(i.e. lowest stringdist)
 
  df1$winner[i] <- df2[which(d == min(d)), 2]
  df1$loser[i] <- df2[which(d == min(d)), 3]
}

#adding another loop that makes the names in the winner/loser columns
#change to their closest match in the player1 and player2 columns

for(i in 1:nrow(df1)){
  n <- stringdist(df1$winner[i], c(df1$player1_name[i], df1$player2_name[i]), method = "cosine")
  if (n[1] > n[2]){df1$winner[i] <- df1$player2_name[i]
                   df1$loser[i] <- df1$player1_name[i]}
  if (n[1] < n[2]){df1$winner[i] <- df1$player1_name[i]
                   df1$loser[i] <- df1$player2_name[i]}
}

> df1
        date    player1_name         player2_name            winner                loser
1 2020-09-29     Laslo Djere       Kevin Anderson    Kevin Anderson          Laslo Djere
2 2020-09-29    Hugo Dellien    Ricardas Berankis Ricardas Berankis         Hugo Dellien
3 2020-09-29   Quentin Halys         Marcos Giron      Marcos Giron        Quentin Halys
4 2020-09-29   Steve Johnson    Roberto Carballes Roberto Carballes        Steve Johnson
5 2020-09-29 Henri Laaksonen         Pablo Cuevas      Pablo Cuevas      Henri Laaksonen
6 2020-09-29 Thiago Monteiro Nikoloz Basilashvili   Thiago Monteiro Nikoloz Basilashvili
7 2020-09-29   Andrej Martin           Joao Sousa     Andrej Martin           Joao Sousa

【讨论】:

  • 并不是有人问过,但我认为 Rublev 至少会打进 RG 的半决赛,他最近很火。
  • 谢谢!这很棒。我认为你没有考虑到日期,但那是微不足道的。我可以很容易地融入这一点。我还在考虑从 df1 返回获胜者和失败者列的值,以便我可以看到它们的全名。这可能需要一点额外的努力,但我想我可以解决。
  • 鲁布列夫在首轮对阵奎雷的比赛中勉强逃过一劫,但我同意他会深入到比赛中。
  • @MohamadSahil 抱歉,在 OP 中错过了这一点。我添加了另一个循环,通过确定两者中哪个名字最接近选定的赢家/输家,然后替换它,使玩家的名字完整。这有点笨拙,所以可能有更好的方法来做到这一点。是的,我认为 Querrey 似乎打到了他所打的任何人的水平,他在很多五盘比赛中。
猜你喜欢
  • 2021-11-02
  • 2020-10-15
  • 1970-01-01
  • 2019-09-02
  • 2020-11-28
  • 1970-01-01
  • 2020-08-31
  • 2019-02-15
  • 2019-10-30
相关资源
最近更新 更多