将一个数据帧中的每一行与tidyverse中另一行的每一行进行比较

Dmytro Fedoriuk

我需要将一个数据帧的每一行与另一数据帧的每一行进行比较:

             id first_name last_name                         account_nr  amount currency comment
1   wW3A4QgpQQd    Lynnett  Labadini      ES46 2569 1625 6669 5490 4624 9655.56      JPY    Z617
2   LsoPIXEMOo5     Velvet   Ritelli  FR60 4478 1591 96PB SIMI FSTO L13 6992.36      PHP    L841
3   L2wBds77Pw8        orv    matfin LB61 6941 CQYE ONER G5T0 KNDU JU5H 6184.38      CAD    o705
4   ME4O9MKlOzO       ring     hecks        BG28 JYPB 4068 09NB FQ7I 6C 4203.54      IDR    Y548
5   d83N7Viwq8k       judd   Riddick       IL36 2200 2898 6944 4508 084 3619.43      IDR    O762
6   1l96680epEy    Edouard  Kapovski   IS73 1064 6186 1231 6178 3743 49 5291.76      BRL    T397
7   7JwvD23oMzC      Jake Rabinovich           KZ80 759G VOHS JHBY L5TY 6994.26      NGN    Y784
8   ZOcg2uprlN6       vere  gravener      SE39 1416 1830 7878 5026 6805 5281.18      UAH    Z890
9   AUrx3nYR2Ks        Bob     Kelso           VS41 5146 7748 1278 5362 4324.12      USD    W312
10 VrDS+DqRG4S1      Mitch  Mitchell           AT65 6306 7334 7478 1908 4221.59      EUR    T352

另一个

            id first_name last_name  amount currency comment recipient
1  xGZx1tNE4oa    Lynnett  Labadini 9655.56      JPY    Z617        72
2  nV7NtxiguPQ     Velvet   Ritelli 6992.36      PHP    L841       175
3  Rto0EHOR17k        Orv    Matfin 6184.38      CAD    O705       412
4  2VDMHTJnxcw       Ring     Hecks 4203.54      IDR    Y548        63
5  VQI7I0EZf1q       Judd   Riddick 3619.43      IDR    O163        39
6  w835JEfmJvZ    Edouard Avramovic 5291.76      BRL    T397       240
7  of2FZZXFKY8      Ferdy Petracchi 6994.26      NGN    Y784       102
8  XgUZFhKowB1       Vere  Gravener 5281.18      IDR    U024       111
9  iGO9advyXP3       Temp McKeevers 7364.49      TND    R404       327
10 5BCiYQVhfxM      Arnie   Ashdown 4221.59      ZAR    N988       262

我想用tidyverse来做,但是另一种方式也是可以接受的。我不想使用循环。ID中没有匹配项。任务是在first_name, last_name, amount, currency, comment上进行模糊连接我看到的一种方法是扩展nrow另一个数据帧时间的每一行并使用map,但是我认为这在内存方面非常低效。

叶亚瑟

使用查看我的解决方案fuzzyjoin基本上,它确实将左侧的每一行散布到右侧的每一行,因为我将max_dist设置为高(10),但是如果您无论如何都不想匹配不好,则可以降低它。然后,它使用group_bytop_n选择第一个数据帧中每个first_name和last_name的最佳匹配。

我添加了“不匹配”和“标签”条件(请参阅前两列)。您可以调整匹配功能选项(现在,它使用特定的stringdist方法Levenshtein比较指定的五列的字符串距离)。

同样,鲍勃·凯索(Bob Kelso)出现两次,因为最佳匹配被绑在2个(不良)匹配之间,因此该算法无法选择同样糟糕的匹配之一。

library(tidyverse); library(fuzzyjoin)

# Load data
df1 <- tibble::tribble(
             ~id, ~first_name,   ~last_name,                          ~account_nr, ~amount, ~currency, ~comment,
   "wW3A4QgpQQd",   "Lynnett",   "Labadini",      "ES46 2569 1625 6669 5490 4624", 9655.56,     "JPY",   "Z617",
   "LsoPIXEMOo5",    "Velvet",    "Ritelli",  "FR60 4478 1591 96PB SIMI FSTO L13", 6992.36,     "PHP",   "L841",
   "L2wBds77Pw8",       "orv",     "matfin", "LB61 6941 CQYE ONER G5T0 KNDU JU5H", 6184.38,     "CAD",   "o705",
   "ME4O9MKlOzO",      "ring",      "hecks",        "BG28 JYPB 4068 09NB FQ7I 6C", 4203.54,     "IDR",   "Y548",
   "d83N7Viwq8k",      "judd",    "Riddick",       "IL36 2200 2898 6944 4508 084", 3619.43,     "IDR",   "O762",
   "1l96680epEy",   "Edouard",   "Kapovski",   "IS73 1064 6186 1231 6178 3743 49", 5291.76,     "BRL",   "T397",
   "7JwvD23oMzC",      "Jake", "Rabinovich",           "KZ80 759G VOHS JHBY L5TY", 6994.26,     "NGN",   "Y784",
   "ZOcg2uprlN6",      "vere",   "gravener",      "SE39 1416 1830 7878 5026 6805", 5281.18,     "UAH",   "Z890",
   "AUrx3nYR2Ks",       "Bob",      "Kelso",           "VS41 5146 7748 1278 5362", 4324.12,     "USD",   "W312",
  "VrDS+DqRG4S1",     "Mitch",   "Mitchell",           "AT65 6306 7334 7478 1908", 4221.59,     "EUR",   "T352"
  )
df2 <- tibble::tribble(
                   ~id, ~first_name,  ~last_name, ~amount, ~currency, ~comment, ~recipient,
         "xGZx1tNE4oa",   "Lynnett",  "Labadini", 9655.56,     "JPY",   "Z617",         72,
         "nV7NtxiguPQ",    "Velvet",   "Ritelli", 6992.36,     "PHP",   "L841",        175,
         "Rto0EHOR17k",       "Orv",    "Matfin", 6184.38,     "CAD",   "O705",        412,
         "2VDMHTJnxcw",      "Ring",     "Hecks", 4203.54,     "IDR",   "Y548",         63,
         "VQI7I0EZf1q",      "Judd",   "Riddick", 3619.43,     "IDR",   "O163",         39,
         "w835JEfmJvZ",   "Edouard", "Avramovic", 5291.76,     "BRL",   "T397",        240,
         "of2FZZXFKY8",     "Ferdy", "Petracchi", 6994.26,     "NGN",   "Y784",        102,
         "XgUZFhKowB1",      "Vere",  "Gravener", 5281.18,     "IDR",   "U024",        111,
         "iGO9advyXP3",      "Temp", "McKeevers", 7364.49,     "TND",   "R404",        327,
         "5BCiYQVhfxM",     "Arnie",   "Ashdown", 4221.59,     "ZAR",   "N988",        262
         )

# Solution using fuzzyjoin
stringdist_left_join(df1, df2, by = c("first_name", "last_name", "amount", "currency", "comment"), 
                     max_dist = 10, ignore_case = TRUE, method = "lv", distance_col = "dist") %>%
  mutate(total.dist = first_name.dist + last_name.dist + amount.dist + currency.dist + comment.dist) %>%
  group_by(first_name.x, last_name.x) %>%
  top_n(-1, total.dist) %>%
  mutate(mismatch = (first_name.dist>0) + (last_name.dist>0) + (amount.dist>0) + (currency.dist>0) + (comment.dist>0),
         label = case_when(mismatch == 0 ~ "match",
                           mismatch == 1 ~ "high",
                           mismatch == 2 ~ "proposed",
                           mismatch > 2 ~ "none",
                           TRUE ~ "")) %>%
  select(label, mismatch, total.dist, everything())
#> # A tibble: 11 x 22
#> # Groups:   first_name.x, last_name.x [10]
#>    label mismatch total.dist id.x  first_name.x last_name.x account_nr
#>    <chr>    <int>      <dbl> <chr> <chr>        <chr>       <chr>     
#>  1 match        0          0 wW3A~ Lynnett      Labadini    ES46 2569~
#>  2 match        0          0 LsoP~ Velvet       Ritelli     FR60 4478~
#>  3 match        0          0 L2wB~ orv          matfin      LB61 6941~
#>  4 match        0          0 ME4O~ ring         hecks       BG28 JYPB~
#>  5 high         1          2 d83N~ judd         Riddick     IL36 2200~
#>  6 high         1          7 1l96~ Edouard      Kapovski    IS73 1064~
#>  7 prop~        2         14 7Jwv~ Jake         Rabinovich  KZ80 759G~
#>  8 prop~        2          7 ZOcg~ vere         gravener    SE39 1416~
#>  9 none         5         20 AUrx~ Bob          Kelso       VS41 5146~
#> 10 none         5         20 AUrx~ Bob          Kelso       VS41 5146~
#> 11 none         4         19 VrDS~ Mitch        Mitchell    AT65 6306~
#> # ... with 15 more variables: amount.x <dbl>, currency.x <chr>,
#> #   comment.x <chr>, id.y <chr>, first_name.y <chr>, last_name.y <chr>,
#> #   amount.y <dbl>, currency.y <chr>, comment.y <chr>, recipient <dbl>,
#> #   amount.dist <dbl>, comment.dist <dbl>, currency.dist <dbl>,
#> #   first_name.dist <dbl>, last_name.dist <dbl>

reprex软件包(v0.2.1)创建于2019-03-17

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将数据帧中的每一行与 r 中另一个数据帧中的每一行进行匹配

将数据框中的每一行与另一个数据框中的多行进行比较并获得结果

如何将数据帧1的每一行与数据帧2的每一行进行比较?

如何将一个数据框的每一行与另一数据框的所有行进行比较并计算距离度量?

将一行中的每个列与数据库sql中的每一行进行比较

将一个数据集的每一行与另一数据集进行比较

在将第一行与第二个 DF 中的多行进行比较后,将 DF 中的每一行映射到另一个 DF 中的一行的最佳方法是什么?

将一个数据帧乘以另一个数据帧中的每一行并聚合结果

为另一个数据帧中的每一行复制并连接熊猫数据帧

将txt文件中的每一行与每一行中的另一个文本文件进行比较

如何将数据帧的每一行与R中的数据帧进行比较?

Perl:将文件的每一行与该文件的每一行进行比较

如何将数据帧中的每一列与另一个数据帧熊猫中的一行相乘?

Python:将矩阵中的每一行与其他每一行进行比较之后,存储非零唯一行的索引

将矩阵的每一行与另一矩阵中的同一行进行交互

如何将一个数据帧中的一行的值与另一个数据帧中的多个行进行比较(包括计算)

如何将数据帧附加到另一个数据帧的每一行?

将每一行与数据框中的所有行进行比较,并将结果保存在每一行的列表中

在熊猫中从一个数据帧到另一个数据帧的每一行迭代差异

将每一行分配给另一个表中的每一行

如何将每一行与所有其他行进行比较,如果相同,我将连接到一个新的数据帧?Python

如何在python中对pandas数据帧的每一行进行计算?

Kusto:将结果集中的每一行与另一个表进行比较

如何编写一个查询,将一个表的每一行与MySQL中不同表的所有行进行比较?

比较R中两个数据帧中的每一行

将变量与txt文件中的每一行进行比较

Python将文件中的每一行与其他所有行进行比较

将每一行与data.frame中的所有其他行进行比较

将一个数据框中的值附加或连接到 Pandas 中另一个数据框中的每一行