1

本着该线程的精神(当键列数不同时合并 data.table),我如何将表 A 中的键列匹配到单个值(来自表或非表),其中 A 中的匹配行是什么时候A 中至少有一列等于该值?

这是一个简短的示例:假设我有表 A:

A <- data.table(b1 = c(0, 1, 1, 1, 1), b2 = c(1, 1, 1, 1, 0), b3 = c(1, 0, 1, 1, 0), mis = FALSE)
setkey(A, b1, b2, b3)

假设我想在 A 的至少一列中匹配的值是 0。所以 A 中的匹配行将是第 1、2 和 5 行。我可以使用以下方法得到这个结果:

A[b1 == 0 | b2 == 0 | b3 == 0, ] # this is not so fast if A is large

    b1 b2 b3
1:  0  1  1
2:  1  1  0
3:  1  0  0

是否有可能获得相同的结果但使用更快的连接或合并操作?

我尝试了一些事情,例如:

B <- data.table(v = 0)
A[B, ] # only matches with column b1 in A

或这个:

B <- data.table[b1 = 0, b2 = 0, b2 = 0]
setkey(B, b1, b2, b3)
A[B, ] # matches when all three corresponding columns match

是否有可能想出一个公式来利用二分搜索的速度来实现我正在寻找的结果?

非常感谢你的帮助!

4

2 回答 2

1

获得一点改进的一个简单技巧是使用连接进行第一次比较:

A[J(0), mis := TRUE]
A[b2 == 0 | b3 == 0, mis := TRUE]

请注意,虽然简单的比较总是比setkey+ join 快 - 所以只有在你多次执行 joinsetkey或者密钥已出于不同原因设置的情况下才有意义。


经过一番思考 - 您可以通过减少所涉及的操作数量(减少到 3 个而不是原来的 5 个)来显着加快速度。以下工作有点令人惊讶,因为它用可能更昂贵的操作替换了操作(至少天真地我认为乘法会更昂贵),但它速度大约是 2 倍:

A[b1 * b2 * b3 == 0, mis := TRUE]
于 2013-11-06T16:24:30.927 回答
0

我假设您的示例是一个一般示例,而不是您正在处理的实际问题,所以我对数据采取了一些自由 -

library(data.table)
A <- data.table(
b1 = c(0, 1, 1, 1, 2), 
b2 = c(1, 2, 1, 1, 0), 
b3 = c(3, 0, 1, 1, 0)
)

Azerolist <- vector(mode = "list",length = ncol(A))

B1 <- data.table(
b11 = 0
)
setkeyv(A,c("b1"))
setkeyv(B1,c("b11"))
Azerolist[[1]] <- A[B1]
# b1 is zero, b2 or b3 might or might not be

B2 <- data.table(
b21 = 0,
b11 = 1
)
setkeyv(A,c("b2","b1"))
setkeyv(B2,c("b21","b11"))
Azerolist[[2]] <- A[B1, roll = Inf]
# b1 is not zero, b2 is zero, b3 might or might not be

B3 <- data.table(
b31 = 0,
b01 = 1
)
setkeyv(A,c("b3","b2"))
setkeyv(B3,c("b31","b01"))
A2 <- A[B1, roll = Inf]
setkeyv(A2,c("b3","b1"))
Azerolist[[3]] <- A2[B3, roll = Inf]
# b1 is not zero, b2 is not zero, b3 is zero

#ordering the columns in the same order for all data.tables in the list
Azerolist <- lapply(Azerolist, function(x) x[,colnames(A), with = FALSE])
# tada!
Azerodt <- rbindlist(Azerolist)
于 2013-11-06T15:37:36.070 回答