【问题标题】:Fuzzy join with 2 large data frames带有 2 个大数据帧的模糊连接
【发布时间】:2020-04-02 14:59:11
【问题描述】:

这是我的例子:

id <- 1:5
names_1 <- c("hannah", "marcus", "fred", "joe", "lara")
df_1 <- data.frame(id, names_1)
df_1$phonenumberFound <- NA


names_2 <- c("hannah", "markus", "fredd", "joey", "paul", "mary", "olivia")
phone <- c(123, 234, 345, 456, 567, 678, 789)
df_2 <- data.frame(names_2, phone)

我想要实现的是:

如果 df_2 中的一个名字(至少近似)匹配 df_1 中的一个名字,那么我想在 df_1 中添加相应的电话号码。

基本上,这是一种模糊的左连接,但我没有成功。

事实上,我真正的 df_1 有 30.000 行,而我真正的 df_2 有 500.000 行。有没有快速的方法来做到这一点?

谢谢!

编辑:

我需要更改和澄清我的示例,因为我使用目前提供的答案遇到了内存问题。 (我使用的是 16 GB RAM 的 Windows 笔记本。)

id_1 <- 1:30000
names_1 <- sample(c("hannah", "marcus", "fred", "joe", "lara"), 30000, replace = TRUE, prob = c(0.2, 0.2, 0.2, 0.2, 0.2))
df_1 <- data.frame(id_1, names_1)
df_1$numberFound <- NA

id_2 <- 1:500000
names_2 <- sample(c("hannah", "markus", "paul", "mary", "olivia"), 500000, replace = TRUE, prob = c(0.2, 0.2, 0.2, 0.2, 0.2))
anyNumber <- sample(c(123, 234, 345, 456, 567), 500000, replace = TRUE, prob = c(0.2, 0.2, 0.2, 0.2, 0.2))
df_2 <- data.frame(id_2, names_2, anyNumber)

非常感谢任何有用的 cmets 和答案。

【问题讨论】:

    标签: r dataframe fuzzyjoin


    【解决方案1】:

    我们可以使用adist 来计算字符向量之间的字符串距离。

    adist(df_1$names_1, df_2$names_2)
    #     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
    #[1,]    0    5    6    6    5    5    6
    #[2,]    5    1    5    6    4    3    6
    #[3,]    6    5    1    3    4    4    6
    #[4,]    6    6    4    1    4    4    6
    #[5,]    4    4    5    4    3    2    4
    

    定义一些可以允许的合适阈值并分配相应的phone列。

    thresh <- 1
    mat <- adist(df_1$names_1, df_2$names_2) <= thresh
    inds <- max.col(mat) * (rowSums(mat) > 0)
    df_1$phone <- df_2$phone[replace(inds, inds == 0, NA)]
    
    df_1
    #  id names_1 phone
    #1  1  hannah   123
    #2  2  marcus   234
    #3  3    fred   345
    #4  4     joe   456
    #5  5    lara    NA
    

    但是,由于这会生成 mn 矩阵,因此它可能不是最有效的方法。

    【讨论】:

    • 也不错,但我又遇到了内存问题。
    • 是的...如果数据太大,这将导致内存问题,除非您有大量内存。
    • @RamiAl-Fahham 解决内存问题的方法是对数据进行分块,看看你是否可以对每个数据集中的某些特征进行子集化,这可能有助于你告诉模糊数学算法忽略所有最不可能的匹配情况 - 很多可能的匹配(尤其是远距离匹配)将是多余的。
    【解决方案2】:

    这是fuzzyjoin的一个选项

    library(fuzzyjoin)
    stringdist_right_join((df_2, df_1, by = c("names_2" = "names_1")) %>%
          select(names(df_1), phone)
    #  id names_1 phone
    #1  1  hannah   123
    #2  2  marcus   234
    #3  3    fred   345
    #4  4     joe   456
    #5  5    lara   678
    

    或者使用来自stringdist 包的stringdistmatrix 创建一个矩阵

    library(stringdist)
    df_2$phone[max.col(-stringdistmatrix(df_1$names_1, df_2$names_2), 'first')]
    

    【讨论】:

    • 谢谢,但我遇到了“错误:无法分配大小为 68.2 Gb 的向量”,我真的不明白为什么。
    猜你喜欢
    • 2020-07-08
    • 2019-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    相关资源
    最近更新 更多