数据和上下文优先:有问题的数据是
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
由于合并?
答案 0 :(得分:2)
使用 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