合并关于近似值的两个数据集

时间:2015-04-01 10:37:23

标签: r dataset

我需要合并(左连接)两个数据集xy

merge(x,y, by.x = "z", by.y = "zP", all.x = TRUE)

z中的zP的每个值都不在zP中,但zP中必须有最接近的值。因此,我们需要在z <- c(0.231, 0.045, 0.632, 0.217, 0.092, ...) zP <- c(0.010,0.013, 0.017, 0.021, ...) 中使用最近的值来进行合并。 例如

{{1}}

我们怎样才能在R?中做到这一点?

1 个答案:

答案 0 :(得分:1)

根据您提供的信息,您可能希望将所有观察结果保留在x中,然后针对x中的每个观察结果,您希望在y中找到观察结果最小化列zzP之间的距离。如果这是你正在寻找的东西那么这样的东西可能会起作用

> library(data.table)

> x <- data.table(z = c(0.231, 0.045, 0.632, 0.217, 0.092), k = c("A","A","B","B","B"))
> y <- data.table(zP = c(0.010, 0.813, 0.017, 0.421), m = c(1,2,3,4))

> x
       z k 
1: 0.231 A 
2: 0.045 A 
3: 0.632 B 
4: 0.217 B 
5: 0.092 B 
> y
      zP m
1: 0.010 1
2: 0.813 2
3: 0.017 3
4: 0.421 4

> find.min.zP <- function(x){
+   y[which.min(abs(x - zP)), zP]
+ }

> x[, zP := find.min.zP(z), by = z]

> x
   z k    zP
1: 0.231 A 0.421
2: 0.045 A 0.017
3: 0.632 B 0.813
4: 0.217 B 0.017
5: 0.092 B 0.017

> merge(x, y, by="zP", all.x = T, all.y = F)
      zP     z k m
1: 0.017 0.045 A 3
2: 0.017 0.217 B 3
3: 0.017 0.092 B 3
4: 0.421 0.231 A 4
5: 0.813 0.632 B 2

这是解决方案,因为我使用data.table了很多。请注意,在这里使用data.table可能是也可能不是最优雅的方式,它甚至可能不是最快的方式(尽管如果xy很大,某些解决方案涉及{{1可能会是最快的)。另请注意,这可能是使用data.table&#34;严重&#34;因为我没有做出任何优化速度的努力。如果速度很重要,我强烈建议您阅读github wiki上的有用文档。希望有所帮助。

编辑:

正如我所怀疑的,data.table提供了一种更好的方式,Arun在评论中指出。

data.table

唯一的区别是,> setkey(x, z) > setkey(y, zP) > y[x, roll="nearest"] zP m k 1: 0.045 3 A 2: 0.092 3 B 3: 0.217 3 B 4: 0.231 4 A 5: 0.632 2 B 列现在名为z,原始zP列已消失。如果保留该列非常重要,您可以随时将zP中的zP列复制到名为y的新列并加入该列。

z

这种打字略微减少,但真正的改进是大数据集的计算时间。

> y[, z := zP]
> setkey(x, z)
> setkey(y, z)
> y[x, roll='nearest']
      zP m     z k
1: 0.017 3 0.045 A
2: 0.017 3 0.092 B
3: 0.017 3 0.217 B
4: 0.421 4 0.231 A
5: 0.813 2 0.632 B

请注意,更快的方法快了2,365倍!我预计,对于观测数超过100,000的数据集来说,时间收益会更加显着(这些日子相对较小)。这就是为什么阅读> x <- data.table(z = runif(100000, 0, 100), k = sample(LETTERS, 100000, replace = T)) > y <- data.table(zP = runif(50000, 0, 100), m = sample(letters, 50000, replace = T)) > start <- proc.time() > x[, zP := find.min.zP(z), by = z] > slow <- merge(x, y, by="zP", all.x = T, all.y = F) > proc.time() - start user system elapsed 104.849 0.072 106.432 > x[, zP := NULL] # Drop the zP column we added to x doing the merge the slow way > start <- proc.time() > y[, z := zP] > setkey(x, z) > setkey(y, z) > fast <- y[x, roll='nearest'] > proc.time() - start user system elapsed 0.046 0.000 0.045 # Reorder the rows and columns so that we can compare the two data tables > setkey(slow, z) > setcolorder(slow, c("z", "zP", "k", "m")) > setcolorder(fast, c("z", "zP", "k", "m")) > all.equal(slow, fast) TRUE 文档是值得的,如果您正在处理大型数据集。你通常可以通过使用内置方法实现非常大的加速,但除非你看,否则你不会知道他们会在那里。