【问题标题】:R merge.data.frame: probabilistic result for ambiguous keysR merge.data.frame:模糊键的概率结果
【发布时间】:2016-03-04 00:05:14
【问题描述】:

数据和上下文优先:有问题的数据是

set.seed(123)
df1 <- data.frame(A = rep(1, 4), B = c(2, 6, 4, 4), D = c(0.1, 0.2, 0.3, 0.4))
df2 <- data.frame(A = rep(1, 4), C = c(2, 4, 6, 4), D = c(0.5, 0.6, 0.7, 0.8))

所以我们有

> df1
  A B   D
1 1 2 0.1
2 1 6 0.2
3 1 4 0.3
4 1 4 0.4

> df2
  A C   D
1 1 2 0.5
2 1 4 0.6
3 1 6 0.7
4 1 4 0.8

现在,当做时

merge(df1, df2, by.x = c("A", "B"), by.y = c("A", "C"))

一个得到

  A B D.x D.y
1 1 2 0.1 0.5
2 1 4 0.3 0.6
3 1 4 0.3 0.8
4 1 4 0.4 0.6
5 1 4 0.4 0.8
6 1 6 0.2 0.7

因为 (A,B) 和 (A,C) 值的组合不明确。

实际问题:如何通过将 D.x 和 D.y 随机分配给 (A,B) 来解决这个问题,例如获得同样的可能性

  A B D.x D.y
1 1 2 0.1 0.5
2 1 4 0.3 0.6
5 1 4 0.4 0.8
6 1 6 0.2 0.7

  A B D.x D.y
1 1 2 0.1 0.5
3 1 4 0.3 0.8
4 1 4 0.4 0.6
6 1 6 0.2 0.7

作为合并的结果?

【问题讨论】:

    标签: r merge duplicates


    【解决方案1】:

    使用 data.table 包,您可以这样做:

    library(data.table)
    DT <- dt1[dt2, on = c(A="A", B="C")][, .(i.D = sample(i.D,1)), by = .(A, B, D)]
    

    这给出了两种可能的结果(从上面运行代码几次以查看不同的结果):

    > DT
       A B   D i.D
    1: 1 2 0.1 0.5
    2: 1 4 0.3 0.6
    3: 1 4 0.4 0.8
    4: 1 6 0.2 0.7
    

    或:

    > DT
       A B   D i.D
    1: 1 2 0.1 0.5
    2: 1 4 0.3 0.8
    3: 1 4 0.4 0.6
    4: 1 6 0.2 0.7
    

    虽然这个简单的解决方案有效,但效率会降低(尤其是在内存使用方面)。导致相同结果的内存效率更高的解决方案是:

    dt1[, indx := 1:.N, keyby = .(A, B)]
    dt2[, indx := if(.N > 1L) sample(.N) else 1L, keyby = .(A, C)]
    dt1[dt2, on = c(A = "A", B = "C", indx = "indx")]
    

    通过在两个数据集中创建索引并为第二个数据集采样该索引,您可以加入该索引。这可以防止所有可能的组合首先包含在连接中的笛卡尔连接。


    使用过的数据:

    dt1 <- data.table(A = rep(1, 4), B = c(2, 6, 4, 4), D = c(0.1, 0.2, 0.3, 0.4))
    dt2 <- data.table(A = rep(1, 4), C = c(2, 4, 6, 4), D = c(0.5, 0.6, 0.7, 0.8))
    

    在基础 R 中你可以这样做:

    df12 <- merge(df1, df2, by.x = c("A", "B"), by.y = c("A", "C"))
    
    aggregate( . ~ A + B + D.x, df12, sample, 1)
    

    这在aggregate 函数的三个连续运行中为我提供了以下三个结果:

    # run 1
      A B D.x D.y
    1 1 2 0.1 0.5
    2 1 6 0.2 0.7
    3 1 4 0.3 0.6
    4 1 4 0.4 0.8
    
    # run 2
      A B D.x D.y
    1 1 2 0.1 0.5
    2 1 6 0.2 0.7
    3 1 4 0.3 0.8
    4 1 4 0.4 0.8
    
    # run 3
      A B D.x D.y
    1 1 2 0.1 0.5
    2 1 6 0.2 0.7
    3 1 4 0.3 0.8
    4 1 4 0.4 0.6
    

    【讨论】:

    • 感谢您的解决方案,点赞。由于我(还没有?)熟悉data.table,我更喜欢base 解决方案。我会把它打开,以防有人插话。如果没有,我会在一段时间后接受。
    • @phaebz 添加了基础 R 解决方案
    • 谢谢!我认为这是我应该更仔细地调查data.table 的地方。暂时推迟……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    相关资源
    最近更新 更多