如何在R中使用fuzzyjoin :: difference_ *执行模糊连接

问题描述:

我正在处理两个基于阈值合并的不同数据集。比方说,两个dataframes是这样的:如何在R中使用fuzzyjoin :: difference_ *执行模糊连接

library(dplyr) 
library(fuzzyjoin) 
library(lubridate) 

df1 = data_frame(Item=1:5, 
       DateTime=c("2015-01-01 11:12:14", "2015-01-02 09:15:23", 
          "2015-01-02 15:46:11", "2015-04-19 22:11:33", 
          "2015-06-10 07:00:00"), 
       Count=c(1, 6, 11, 15, 9), 
       Name="Sterling", 
       Friend=c("Pam", "Cyril", "Cheryl", "Mallory", "Lana")) 
df1$DateTime = ymd_hms(df1$DateTime) 

df2 = data_frame(Item=21:25, 
       DateTime=c("2015-01-01 11:12:15", "2015-01-02 19:15:23", 
          "2015-01-02 15:46:11", "2015-05-19 22:11:33", 
          "2015-06-10 07:00:02"), 
       Count=c(3, 7, 11, 15, 8), 
       Name="Sterling", 
       Friend=c("Pam", "Kreger", "Woodhouse", "Gillete", "Lana")) 
df2$DateTime = ymd_hms(df2$DateTime) 

我现在想什么,是能够基于对DateTime模糊匹配和Count是各自的价值在两秒钟内左连接df2df1,而除Item以外的所有其他值都相同。我以为我可以用下面的路线:

df1 %>% 
    difference_left_join(df2, by=c("DateTime", "Count"), max_dist=2) 

但是,这给了我下面的输出:

# A tibble: 8 × 10 
    Item.x   DateTime.x Count.x Name.x Friend.x Item.y   DateTime.y Count.y Name.y Friend.y 
    <int>    <dttm> <dbl> <chr> <chr> <int>    <dttm> <dbl> <chr>  <chr> 
1  1 2015-01-01 11:12:14  1 Sterling  Pam  21 2015-01-01 11:12:15  3 Sterling  Pam 
2  1 2015-01-01 11:12:14  1 Sterling  Pam  21 2015-01-01 11:12:15  3 Sterling  Pam 
3  2 2015-01-02 09:15:23  6 Sterling Cyril  NA    <NA>  NA  <NA>  <NA> 
4  3 2015-01-02 15:46:11  11 Sterling Cheryl  23 2015-01-02 15:46:11  11 Sterling Woodhouse 
5  3 2015-01-02 15:46:11  11 Sterling Cheryl  23 2015-01-02 15:46:11  11 Sterling Woodhouse 
6  4 2015-04-19 22:11:33  15 Sterling Mallory  NA    <NA>  NA  <NA>  <NA> 
7  5 2015-06-10 07:00:00  9 Sterling  Lana  25 2015-06-10 07:00:02  8 Sterling  Lana 
8  5 2015-06-10 07:00:00  9 Sterling  Lana  25 2015-06-10 07:00:02  8 Sterling  Lana 

这是接近,除了第3行不应该合并,因为名称不同(并且我希望第2行在给定阈值的情况下合并,即使我不希望它)。

如何结束以下数据框?请注意,尽管DateTimeCount满足阈值限制,但df2的第二行和第三行未合并。这是因为其他列(Item除外)不相同。

desired_output 
# Item   DateTime Count  Name Friend 
# 1 3 2015-01-02 15:46:11 11 Sterling Cheryl 
# 2 2 2015-01-02 09:15:23  6 Sterling Cyril 
# 3 5 2015-06-10 07:00:00  9 Sterling Lana 
# 4 25 2015-06-10 07:00:02  8 Sterling Lana 
# 5 4 2015-04-19 22:11:33 15 Sterling Mallory 
# 6 1 2015-01-01 11:12:14  1 Sterling  Pam 
# 7 21 2015-01-01 11:12:15  3 Sterling  Pam 
+0

我认为如果您在连接之前不对数据使用'lubridate',它会给您提到的错误。否则,如果给你一个不同的信息。 BTW对不起,如果我错过了明显的东西,但“持续时间”从哪里来? –

+1

啊,对不起!我弄糟了数据来掩盖它的真实含义,但是保留了真正的变量名称。我会把它清理干净。 – brittenb

+0

鉴于您指出为什么会发生错误,并且更新了调用该行代码的结果,还删除了对错误的引用。 – brittenb

好的,所以,你得到的消息是因为模糊匹配无法在非数字列上计算。

要做的事情是将其转换为数字。由于您的卡钳是在几秒钟内我把它转换成秒,然后让他们的数字:

library(dplyr) 
library(fuzzyjoin) 
library(lubridate) 

df1 = data_frame(Item=1:5, 
       DateTime=c("2015-01-01 11:12:14", "2015-01-02 09:15:23", 
          "2015-01-02 15:46:11", "2015-04-19 22:11:33", 
          "2015-06-10 07:00:00"), 
       Count=c(1, 6, 11, 15, 9), 
       Name="Sterling", 
       Friend=c("Pam", "Cyril", "Cheryl", "Mallory", "Lana")) 
df1$DateTime1 = as.numeric(seconds(ymd_hms(df1$DateTime))) 

df2 = data_frame(Item=21:25, 
       DateTime=c("2015-01-01 11:12:15", "2015-01-02 19:25:56", 
          "2015-01-02 15:46:11", "2015-05-19 22:11:33", 
          "2015-06-10 07:00:02"), 
       Count=c(3, 6, 11, 15, 8), 
       Name="Sterling", 
       Friend=c("Pam", "Kreger", "Woodhouse", "Gillete", "Lana")) 
df2$DateTime1 = as.numeric(seconds(ymd_hms(df2$DateTime))) 

df1 %>% 
    difference_left_join(y=df2, by=c("DateTime1", "Count"), max_dist=2) 
基于我们在评论一个简单的调整,以子集这对其他字符列的情况下讨论

匹配将是:

df1[df2$Friend == df1$Friend,] %>% 
    difference_left_join(y=df2[df2$Friend == df1$Friend,], by=c("DateTime1", "Count"), max_dist=2) 

该示例仅适用于Friend,但当然,您可以使用&对多列进行此操作。

+0

是否可以指定所有字符变量必须完全匹配?我认为只要从'difference_left_join'获取输出,然后过滤掉其中的记录,例如'Name.x!= Name.y',会更容易。 – brittenb

+0

@brittenb我以为你只希望他们在2秒内匹配? –

+0

无可否认,在重新阅读我的问题和标题后,我并不十分清楚。我希望他们在两秒钟内相互匹配,但只有当每一列(除了“Item”)匹配时才匹配。 – brittenb