我需要合并(左连接)两个数据集x
和y
。
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?中做到这一点?
答案 0 :(得分:1)
根据您提供的信息,您可能希望将所有观察结果保留在x
中,然后针对x
中的每个观察结果,您希望在y
中找到观察结果最小化列z
和zP
之间的距离。如果这是你正在寻找的东西那么这样的东西可能会起作用
> 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
可能是也可能不是最优雅的方式,它甚至可能不是最快的方式(尽管如果x
和y
很大,某些解决方案涉及{{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
文档是值得的,如果您正在处理大型数据集。你通常可以通过使用内置方法实现非常大的加速,但除非你看,否则你不会知道他们会在那里。