【问题标题】:R: Join two data frames via a character column that has small misspellingsR:通过有小拼写错误的字符列连接两个数据帧
【发布时间】:2016-11-14 00:15:37
【问题描述】:

我的两个数据框有相同的字符列。使用 dplyr::full_joint 在此列中加入它们会很容易。但问题是common列在拼写上有细微但明显的差异。与定义技能的每个字符串相比,拼写差异很小:

Skill                   Grade_Judge_A

pack & ship               1
pack & store              5
sell                      3
Design a room             9


Skill                   Grade_Judge_B

pack and store            3
pack & ship               7
sell                      2
Design room               6

如何在下面实现所需的输出:

Skill                   Grade_Judge_A      Grade_Judge_B

pack & ship               1                     3                
pack & store              5                     7
sell                      3                     2
Design a room             9                     6

我正在考虑根据“技能”列中字符串之间的距离匹配两个数据框中的行,例如使用 stringdist 包。如果两根弦的差别很小,说明技能是一样的。

我更喜欢 dplyr/tidyverse 解决方案。

这是数据框 A 的实际输出:

> dput(df_A)

structure(list(skill = c(" [Assess abdomen for a floating mass]", 
" [Assess Nerve Root Compression]", " [Evaluate breathing effort (rate, patterns, chest expansions)]", 
" [Evaluate Plantar Reflex/Babinski sign]", " [Evaluate Speech]", 
" [External palpation of a uterus]", " [Heel to Shin test]", 
" [Inspect anterior chamber of eye with ophthalmoscope or penlight]", 
" [Inspect breast]", " [Inspect Overall Skin Color/Tone]", " [Inspect Skin Lesions]", 
" [Inspect Wounds]", " [Mental Status/level of consciousness]", 
" [Nose/index finger]", " [Percuss abdomen to determine spleen size]", 
" [Percuss costovertebral angle for kidney tenderness]", " [Percuss for diaphragmatic excursion]", 
" [Percuss the abdomen for abdominal tones]", " [Percuss the abdomen to determine liver span]"
), `2016-09-17 13:41:08` = c(1, 1, 5, 3, 4, 0, 4, 3, 3, 5, 4, 
5, 5, 3, 1, 1, 2, 4, 1)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -19L), .Names = c("skill", "2016-09-17 13:41:08"
))

和数据框 B:

> dput(df_B)

structure(list(skill = c(" [Assess abdomen for floating mass]", 
" [Assess nerve root compression]", " [Evaluate breathing effort (rate, patterns, chest expansion)]", 
" [Evaluate plantar reflex/Babinski sign]", " [Evaluate speech]", 
" [External palpation of uterus]", " [Heel to shin test]", " [Inspect anterior chamber of the eye with opthalmoscope or penlight]", 
" [Inspect breasts]", " [Inspect overall skin color/tone]", " [Inspect skin lesions]", 
" [Inspect wounds]", " [Mental status/level of consciousness]", 
" [Nose/Index finger]", " [Percuss costovertebral angle for kidney tenderness]", 
" [Percuss for diaphragmatic excursion]", " [Percuss the abdomen for abdominal tones]", 
" [Percuss the abdomen to determine liver span]", " [Percuss the abdomen to determine spleen size]"
), `2016-09-21 07:58:43` = c(0, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 2)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -19L), .Names = c("skill", "2016-09-21 07:58:43"
))

这是两个数据帧的头部:

 > head(df_A)
        # A tibble: 6 × 2
                                                                    skill `2016-09-17 13:41:08`
                                                                    <chr>                 <dbl>
        1                            [Assess abdomen for a floating mass]                     1
        2                                 [Assess Nerve Root Compression]                     1
        3  [Evaluate breathing effort (rate, patterns, chest expansions)]                     5
        4                         [Evaluate Plantar Reflex/Babinski sign]                     3
        5                                               [Evaluate Speech]                     4
        6                                [External palpation of a uterus]                     0

第二个:

> head(df_B)
# A tibble: 6 × 2
                                                           skill `2016-09-21 07:58:43`
                                                           <chr>                 <dbl>
1                             [Assess abdomen for floating mass]                     0
2                                [Assess nerve root compression]                     2
3  [Evaluate breathing effort (rate, patterns, chest expansion)]                     2
4                        [Evaluate plantar reflex/Babinski sign]                     2
5                                              [Evaluate speech]                     2
6                                 [External palpation of uterus]                     1

【问题讨论】:

  • 您可以在合并之前解决系统差异(例如,将“&”替换为“and”并将所有字符串转换为小写)。但是否也存在随机拼写错误?
  • 另外,如果你想融入宇宙意识,full_joint 可能是合适的,但full_join 应用于数据时会更有效。
  • 不知道会出现哪种类型的拼写错误。众所周知,它们相对于字符串的长度来说很小。定义每个技能的字符串长度为 20 到 60 个字符,但差异很小,例如缺少文章。可以使用 stringdist 来配对技能吗?如果 stringdist 很小,则假定是相同的技能。
  • 是的,stringdist 可能能够解决大多数问题,尽管您可能会遇到一些拼写正确的技能彼此相似的情况。你能提供更多的数据示例吗?使用dput 提供示例数据。

标签: r dataframe dplyr tidyverse


【解决方案1】:

这有多接近?

require(tidyverse)
require(stringdist)

df_A %>%
    rownames_to_column %>%
    mutate(foo=1) %>%
    full_join((df_B %>% rownames_to_column %>% mutate(foo=1)), by='foo') %>%
    select(-foo) %>%
    mutate(dist = stringdist(skill.x, skill.y), norm_dist = dist / length(skill.x)) %>%
    arrange(norm_dist) %>%
    filter(norm_dist < 0.015)

我对@9​​87654322@ 和df_B 进行了真正的(关系代数式)完全联接,如果您拥有的真实数据很大(例如,如果两个数据框都有 1000 行结果),这将炸毁您的数据的连接将是 1,000,000 行)。这种连接是通过创建一个对每一行都相等的虚拟列 foo 然后在虚拟列上连接来完成的。

在 cmets 中提到的 stringdist 包然后针对两个字符串的每个可能组合将 A 行与 B 行进行比较。对于您的示例数据,归一化字符串距离的截止值为 0.015,结果似乎不错。当然,这个任意截断可能会过度适合您的示例数据。

【讨论】:

  • 从示例中可以看出,仅当字符串以相同字母开头时才加入(如果知道有关错误的其他信息,则根据需要进行修改),这样可以大大提高效率。 mutate(foo = tolower(substr(skill, 1, 1)))
【解决方案2】:

如果拼写错误中没有模式,我相信唯一剩下的方法是在加入数据之前确保拼写相同。我们可以用 splitstackshape

library(splitstackshape)

yourdata$skill<-stri_replace_all(yourdata8$skill,"pack & store" ,fixed = "pack and store")

此代码在您的数据集的skill 列中将pack and store 替换为pack &amp; store

【讨论】:

  • 技能是长字符串,但拼写错误是随机且小的(例如大写而不是小写或缺少文章)。存在什么样的拼写错误尚不清楚。众所周知,拼写错误相对于字符串长度来说很小。
  • 不确定,也许你想看看技能栏之间的差异,并在这些差异上标记它们stackoverflow.com/questions/28834459/…
  • 我认为 stringdist 会更好,因为它告诉了两个字符串之间的数字“距离”。我只是不确定如何为数据框实现它
  • 根据他们的文档,您可以查看差异是否超过阈值。这是一个告诉您差异是否大于 1 的示例。 amatch("leia",c("uhura","leela"),maxDist=1)。如果您提供可重现的示例,我会尝试
  • 我添加了来自两个数据帧的行样本的 dput
猜你喜欢
  • 1970-01-01
  • 2021-11-19
  • 2021-11-06
  • 2021-06-06
  • 2020-03-31
  • 2017-10-08
  • 2020-02-13
  • 1970-01-01
  • 2022-08-14
相关资源
最近更新 更多