我不明白为什么连接数据表中键的顺序会产生影响。
考虑将
tmp_dt_1
连接到 tmp_dt_2
的以下(预期)结果:
tmp_dt_1 <-
data.table(a = c(1, 2), b = c(2, 1), c = 1:2)
tmp_dt_2 <-
data.table(a = c(1, 2), b = c(2, 1), d = 1:2)
setkeyv(tmp_dt_1, c("a", "b"))
setkeyv(tmp_dt_2, c("a", "b"))
tmp_dt_1
# Key: <a, b>
# a b c
# <num> <num> <int>
# 1: 1 2 1
# 2: 2 1 2
tmp_dt_2
# Key: <a, b>
# a b d
# <num> <num> <int>
# 1: 1 2 1
# 2: 2 1 2
tmp_dt_1[tmp_dt_2]
# Key: <a, b>
# a b c d
# <num> <num> <int> <int>
# 1: 1 2 1 1
# 2: 2 1 2 2
现在,按
tmp_dt_2
列 b
,然后按 a
。与上面的连接相比,这会产生不同(并且错误)的连接:
setkeyv(tmp_dt_2, c("b", "a"))
tmp_dt_1
# Key: <a, b>
# a b c
# <num> <num> <int>
# 1: 1 2 1
# 2: 2 1 2
tmp_dt_2
# Key: <b, a>
# a b d
# <num> <num> <int>
# 1: 2 1 2
# 2: 1 2 1
tmp_dt_1[tmp_dt_2]
# Key: <a, b>
# a b c d
# <num> <num> <int> <int>
# 1: 1 2 1 2
# 2: 2 1 2 1
在 data.table 中的主索引和辅助索引是什么? 中,
data.table
文档说:
按列setkey(DT, col1, col2)
对行进行排序,然后在每组col1
中按col1
进行排序。这是一个主要索引。行顺序通过 RAM 中的引用进行更改...我们可以互换使用索引和键这两个词。col2
(强调我的)
这些键决定 RAM 中的行顺序,如果
data.table
可以利用此顺序,则可以进行低级优化。 例如,它可以最大限度地减少页面获取并批量复制内存而不是循环。
这意味着顺序很重要。因此,当您按照第二种情况中的顺序指定键时,您实际上是在执行以下操作:
tmp_dt_1[
tmp_dt_2,
on = .(a = b, b = a)
]
如果我们只设置一个键,我们可以更清楚地看到这一点:
all(
tmp_dt_1[tmp_dt_2] ==
tmp_dt_1[tmp_dt_2, on = .(a)]
) # FALSE
all(
tmp_dt_1[tmp_dt_2] ==
tmp_dt_1[tmp_dt_2, on = .(a = b)]
) # TRUE
如果您担心这一点,最简单的方法是使用两个
data.table
相同的向量来设置键,例如
keys <- c("a", "b")
setkeyv(tmp_dt_1, keys)
setkeyv(tmp_dt_2, keys)