【问题标题】:Efficient way to handle string similarity?处理字符串相似性的有效方法?
【发布时间】:2020-06-01 22:27:15
【问题描述】:

我遇到了一些字符串相似性问题。

这就是我的数据的样子(原始数据很大):

SerialNumber                SubSerialID            Date

AGCC0775CFNDA1040TMT775     AVCC0775CFNDA1040     2018/01/08
AGCC0775CFNDA1040           AVCC0775CFNDA1040     2015/12/28
AGCC0775CFNDA10407EC        AVCC0775CFNDA1040     2018/03/17
CH~MT765E~C0765HFNCC1056    BGDC0865HFNKG1043     2019/01/07
2658358                     BGDC0865HFNKG1043     2018/08/09
MT765E~C0765KFNCD1044       C0765KFNCD10          2015/04/07
187A126                     C0765KFNCD10          2017/11/31

...

我的目标是:

SerialNumber                SubSerialID            Date 

AGCC0775CFNDA10407EC        AVCC0775CFNDA1040     2018/03/17
CH~MT765E~C0765HFNCC1056    BGDC0865HFNKG1043     2019/01/07
2658358                     BGDC0865HFNKG1043     2018/08/09
MT765E~C0765KFNCD1044       C0765KFNCD10          2015/04/07
187A126                     C0765KFNCD10          2017/11/31

...

序列号AGCC0775CFNDA1040TMT775AGCC0775CFNDA1040AGCC0775CFNDA10407EC 是同一个东西,但都是由错误引起的。我想保留AGCC0775CFNDA10407EC,因为它有最新的记录日期。但是,我不能直接使用SubSerialIDDate 来过滤这些序列号,因为如果会删除2658358

我曾考虑使用stringdist 来查找字符串相似度作为另一个条件(即,通过 abs(相似度)>1.5 和 abs(相似度)

【问题讨论】:

  • 我一直喜欢 11 月 31 日;-)
  • 11/31 是一个错字......:P

标签: r stringdist


【解决方案1】:

以下重现您的预期输出

library(dplyr)
library(purrr)
df %>%
    mutate(Date = as.Date(Date)) %>%
    mutate_if(is.factor, as.character) %>%
    mutate(dist = map2_dbl(SerialNumber, SubSerialID, adist)) %>%
    group_by(SubSerialID) %>%
    filter(all(dist > 5) | Date == max(Date)) %>%
    ungroup()
## A tibble: 5 x 4
#  SerialNumber             SubSerialID       Date        dist
#  <chr>                    <chr>             <date>     <dbl>
#1 AGCC0775CFNDA10407EC     AVCC0775CFNDA1040 2018-03-17     4
#2 CH~MT765E~C0765HFNCC1056 BGDC0865HFNKG1043 2019-01-07    15
#3 2658358                  BGDC0865HFNKG1043 2018-08-09    15
#4 MT765E~C0765KFNCD1044    C0765KFNCD10      2015-04-07     9
#5 187A126                  C0765KFNCD10      2017-11-30    11

如果SubserialIDSerialNumber 之间的Levenshtein 距离大于5,则保留所有条目(每个SubSerialID)。如果&lt;= 5 有一个距离,则仅保留最大Date 的行。我保留了dist 列进行调试;您可以使用select(-dist) 删除该列。

我不确定这是多么普遍。您将不得不使用 Levenshtein 距离阈值(在本例中我设置为 5)。


样本数据

df <- read.table(text =
"SerialNumber                SubSerialID            Date

AGCC0775CFNDA1040TMT775     AVCC0775CFNDA1040     2018/01/08
AGCC0775CFNDA1040           AVCC0775CFNDA1040     2015/12/28
AGCC0775CFNDA10407EC        AVCC0775CFNDA1040     2018/03/17
CH~MT765E~C0765HFNCC1056    BGDC0865HFNKG1043     2019/01/07
2658358                     BGDC0865HFNKG1043     2018/08/09
MT765E~C0765KFNCD1044       C0765KFNCD10          2015/04/07
187A126                     C0765KFNCD10          2017/11/30", header = T)

【讨论】:

  • 再次感谢您向我展示了这个聪明的想法。我发现了一些特殊情况并使用相同的技巧添加了一个限制以找到我想要的完美结果!真的从你身上学到了很多。 @Maurits Evers
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 2017-03-24
  • 2010-10-28
  • 2010-12-09
  • 2010-10-26
  • 1970-01-01
  • 2017-11-10
相关资源
最近更新 更多