为什么在join带有重复键的data.tables时需要allow.cartesian?

我试图了解J()查找时的逻辑,当R中的data.table中有重复的键时

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

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. 

我真的不明白这一点。 我知道我应该避免在查找function重复的键,我只是想获得一些见解,所以我不会在未来的任何错误。

谢谢你的帮助。 这是一个伟大的工具。

您不必避免重复键。 只要结果不会比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。

话虽如此,我认为马特曾经提到,在“大”联接的情况下(或者联接导致大量的行 – 这可能是我猜测的任意设置),可能只提供错误。 这,如果/如果实现,将联合正确没有这个错误消息的情况下,不联合爆炸的联接。

+1阿伦说的。 我个人一直在使用dplyr来处理这类东西很长时间,而且在一个连接过程中,一个简单的input错误(例如,在一个数据框中的一个列名中)可能会导致笛卡尔乘法,并产生巨大的结果。 Dplyr只是开始做,而没有真正检查它是否至less有足够的内存,在这一点上我的电脑完全冻结,所有的进展都失去了。 data.table中的这个安全措施是为了防止这种情况。