两个数据帧之间文本字符串的不对称部分匹配

问题描述 投票:0回答:1

我有两个数据框:

  • df1 基于调查回复,并包含一个非限制字段,供用户添加其在英国的位置(或拒绝这样做),格式如下(非真实数据):
姓名 地点
爱丽丝 伦敦/利物浦
鲍勃 曼彻斯特
吉姆 没有
大卫 我住在卡迪夫

我有另一个数据框(df2),它是英国城镇的单列列表,如下所示:

城市
曼彻斯特
卡迪夫
伦敦
布莱顿
诺丁汉

我想做的是编写能够:

  • 循环df1

  • 对于位置列中的每个条目,扫描 df2,如果 df2 中的任何城市在 df1 中完全复制,则向 df 1 添加一个新列,以提取第一个匹配项,如下所示:

姓名 地点 位置_精确
爱丽丝 伦敦或布莱顿 伦敦
鲍勃 曼彻斯特 曼彻斯特
吉姆 没有 -
大卫 我住在卡迪夫 卡迪夫

然后我可以使用 location_precise 列通过标准化名称进行进一步分析。常规 left_join/lapply 函数让我困惑的是,我想允许在一个方向上部分匹配(如果 df2 中的城市部分包含在 df1 中),但不允许在另一个方向上部分匹配(如果 df1$location 中的答案是df2 中的城市,例如上例中的“no”和“nottingham”。

我不知道如何使常规 dplyr 函数适应这一点,因为两个数据集中没有公共标识符 - 因此每次连接尝试都会以各种错误结束。否则我就完全束手无策了。我尝试过使用 grep:

df1$location_precise <- lapply(df1$Location, grep, df2$city,value=T)

但这不会获取没有空格的部分匹配项,例如“伦敦/格拉斯哥”

我也尝试过 agrep,但这会错误地识别部分匹配,例如 'No' = 'Nottingham',并且仍然无法识别许多其他部分匹配

r dplyr string-matching
1个回答
0
投票

始终记得放置一个可重现的示例。

我已经拿走了你的表(df1 和 df2),并为两个表添加了一个额外的案例:

df1 <- data.frame(Name = LETTERS[1:5], 
                  Location = c("London/Liverpool", 
                               "London/Glasgow",
                               "Manchester",
                               "No",
                               "I am based in Cardiff"))

df2 <- data.frame(city = c("Manchester",
                           "Cardiff",
                           "London",
                           "Glasgow",
                           "Brighton",
                           "Nottingham"))

sapply(X = df1$Location, FUN = \(x){
  
  out <- df2$city[sapply(X = df2$city, FUN = grepl, x = x, ignore.case = TRUE)]
  
  out <- if(length(out) == 0) "-" else if(length(out) == 1) out else if(length(out) > 1) paste(out, collapse = ", ")
})

输出:

 London/Liverpool        London/Glasgow            Manchester 
         "London"     "London, Glasgow"          "Manchester" 
               No I am based in Cardiff 
              "-"             "Cardiff"

这可能不是最优雅的例子,但你可以尝试一下,我们会改进它。对于存在多个匹配项的情况,我让它显示所有匹配项并用逗号分隔它们。

© www.soinside.com 2019 - 2024. All rights reserved.