Por que é necessário o allow.cartesian quando você entra em data.tables com chaves duplicadas?

Eu estou tentando entender a lógica da pesquisa J () quando há chaves duplicadas em um data.table em R.

Aqui está uma pequena experiência que tentei:

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 

A mensagem de erro que estou recebendo é:

 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. 

Eu realmente não entendo isso. Eu sei que devo evitar chaves duplicadas em uma function de pesquisa, eu só quero ganhar alguma visão para que eu não faça nenhum erro no futuro.

Obrigado uma tonelada por ajuda. Essa é uma ótima ferramenta.

Você não precisa evitar chaves duplicadas. Contanto que o resultado não fique maior que max(nrow(x), nrow(i)) , você não receberá este erro, mesmo que tenha duplicatas. É basicamente uma medida de precaução.

Quando você tem chaves duplicadas, a junit resultante pode, às vezes, ficar muito maior. Como o data.table sabe o número total de linhas que resultarão dessa junit com antecedência suficiente, ele fornece essa mensagem de erro e solicita que você use o argumento allow.cartesian=TRUE se tiver certeza.

Aqui está um exemplo (exagerado) que ilustra a ideia por trás dessa mensagem de erro:

 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 

As duplicatas no DT2 resultaram em 3 vezes o número total de "a" no DT1 (= 1e7). Imagine se você executasse a junit com valores de 1e4 no DT2 , os resultados iriam explodir! Para evitar isso, há o argumento allow.cartesian que por padrão é FALSE.

Dito isto, acho que Matt uma vez mencionou que talvez seja possível apenas fornecer o erro no caso de junções "grandes" (ou junções que resultam em um grande número de linhas - que podem ser configuradas arbitrariamente, eu acho). Isso, quando / se implementado, fará a junit corretamente sem essa mensagem de erro no caso de junções que não explodem combinatoriamente.

+1 para o que Arun disse. Eu pessoalmente tenho usado dplyr para coisas assim por um longo tempo, e um simples erro de digitação (por exemplo, em um nome de coluna em um dos frameworks de dados) durante uma junit poderia resultar em multiplicação cartesiana com um resultado enorme. O Dplyr apenas começa a fazê-lo sem realmente verificar se ele terá memory suficiente, pelo menos no ponto em que meu computador congelou completamente e todo o progresso foi perdido. Esta medida de segurança em dados foi feita para evitar isso.