data.table表连接时键的顺序为何会影响结果?
data.table连接操作中键顺序影响结果的原因解析
我搞不懂为什么对data.table做连接时,键的顺序会导致结果不一样,下面是具体场景:
场景1:键顺序一致时的预期结果
library(data.table) 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
场景2:键顺序不一致时的意外结果
# 修改tmp_dt_2的键顺序为b在前、a在后 setkeyv(tmp_dt_2, c("b", "a")) # 表结构变化(tmp_dt_2按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的键(key)有两个作用:排序依据和连接时的匹配列顺序定义。
当使用x[y]这种默认连接语法时,data.table会按键的顺序进行等值匹配:用左表x的键列依次对应右表y的键列,而不是根据列名匹配。
- 场景1中,两张表的键都是
(a, b),匹配逻辑是tmp_dt_1$a == tmp_dt_2$a且tmp_dt_1$b == tmp_dt_2$b,所以得到正确的一对一匹配。 - 场景2中,tmp_dt_1的键是
(a, b),tmp_dt_2的键是(b, a),此时匹配逻辑变成tmp_dt_1$a == tmp_dt_2$b且tmp_dt_1$b == tmp_dt_2$a,相当于把两张表的a、b列交叉匹配,最终导致结果错位。
解决方案
如果不想受键顺序影响,连接时显式指定匹配列即可,用on参数明确列名对应关系:
# 不管键顺序如何,按a、b列名匹配 tmp_dt_1[tmp_dt_2, on = .(a, b)]
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

