为什么在使用重复键加入data.tables时需要allow.cartesian?

时间:2014-04-15 14:54:39

标签: r data.table

当我在R中的data.table中存在重复键时,我试图理解J()查找的逻辑。

这是我尝试过的一个小实验:

library(data.table)
options(stringsAsFactors = FALSE)

x <- data.table(keyVar = c("a", "b", "c", "c"),
            value  = c(  1,   2,   3,   4))
setkey(x, keyVar)

y1 <- data.frame(name = c("d", "c", "a"))
x[J(y1$name), ]
## OK

y2 <- data.frame(name = c("d", "c", "a", "b"))
x[J(y2$name), ]
## Error: see below

x2 <- data.table(keyVar = c("a", "b", "c"),
                 value  = c(  1,   2,   3))
setkey(x2, keyVar)
x2[J(y2$name), ]
## OK

我收到的错误消息是:

Error in vecseq(f__, len__, if (allow.cartesian) NULL else as.integer(max(nrow(x),  :
Join results in 5 rows; more than 4 = max(nrow(x),nrow(i)). Check for duplicate key
values in i, each of which join to the same group in x over and over again. If that's
ok, try including `j` and dropping `by` (by-without-by) so that j runs for each group
to avoid the large allocation. If you are sure you wish to proceed, rerun with 
allow.cartesian=TRUE. Otherwise, please search for this error message in the FAQ, Wiki, 
Stack Overflow and datatable-help for advice.

我真的不明白这一点。我知道我应该避免在查找函数中使用重复键,我只想获得一些见解,以便将来不会出现任何错误。

非常感谢你的帮助。这是一个很棒的工具。

1 个答案:

答案 0 :(得分:28)

您不必避免重复的密钥。只要结果不会超过max(nrow(x), nrow(i)),即使您重复,也不会出现此错误。这基本上是一种预防措施。

当您复制密钥时,生成的联接有时会变得更大。由于data.table足够早地知道此连接所产生的总行数,因此它会提供此错误消息并要求您使用参数allow.cartesian=TRUE,如果您确定的话。

这是一个(夸大的)示例,说明了此错误消息背后的想法:

require(data.table)
DT1 <- data.table(x=rep(letters[1:2], c(1e2, 1e7)), 
                  y=1L, key="x")
DT2 <- data.table(x=rep("b", 3), key="x")

# not run
# DT1[DT2] ## error

dim(DT1[DT2, allow.cartesian=TRUE])
# [1] 30000000        2

DT2中的重复项导致DT1(= 1e7)中“a”总数的3倍。想象一下,如果你在DT2中使用1e4值执行连接,结果会爆炸!为了避免这种情况,有allow.cartesian参数,默认情况下为FALSE。

话虽这么说,我认为Matt曾经提到过,在“大”连接(或者连接导致大量行 - 可能是我猜的任意设置)的情况下,可能只提供错误。如果/如果实现的话,这将使连接正确,如果没有组合爆炸的连接,则没有此错误消息。