¿Por qué se requiere allow.cartesian en momentos cuando se une a data.tables con claves duplicadas?

Estoy tratando de entender la lógica de la búsqueda J () cuando hay claves duplicadas en una tabla de datos en R.

Aquí hay un pequeño experimento que he intentado:

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 

El mensaje de error que recibo es:

 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. 

Realmente no entiendo esto. Sé que debo evitar duplicar claves en una función de búsqueda, solo quiero obtener una idea para no cometer ningún error en el futuro.

Muchas gracias por la ayuda. Esta es una gran herramienta.

No tienes que evitar las llaves duplicadas. Siempre que el resultado no sea mayor que max(nrow(x), nrow(i)) , no obtendrá este error, incluso si tiene duplicados. Básicamente es una medida de precaución.

Cuando tienes claves duplicadas, la unión resultante a veces puede ser mucho más grande. Dado que data.table conoce el número total de filas que resultarán de esta unión lo suficientemente temprano, proporciona este mensaje de error y le pide que use el argumento allow.cartesian=TRUE si está realmente seguro.

Aquí hay un ejemplo (exagerado) que ilustra la idea detrás de este mensaje de error:

 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 

Los duplicados en DT2 dieron como resultado 3 veces el número total de "a" en DT1 (= 1e7). Imagine que si realiza la unión con los valores 1e4 en DT2 , ¡los resultados explotarían! Para evitar esto, existe el argumento allow.cartesian que por defecto es FALSE.

Una vez dicho esto, creo que Matt mencionó una vez que quizás sea posible proporcionar el error en el caso de las uniones "grandes" (o uniones que dan como resultado un gran número de filas, lo que podría establecerse arbitrariamente, supongo). Esto, cuando / si se implementa, hará que la unión sea adecuada sin este mensaje de error en caso de uniones que no explotan combinatoriamente.

+1 a lo que dijo Arun. Personalmente he estado usando dplyr para este tipo de cosas durante mucho tiempo, y un simple error tipográfico (por ejemplo, en el nombre de una columna en uno de los marcos de datos) durante una unión podría dar como resultado una multiplicación cartesiana con un resultado enorme. Dplyr simplemente comienza a hacerlo sin verificar realmente si al menos tendrá suficiente memoria, momento en el que mi computadora se congeló por completo y se perdió todo el progreso. Esta medida de seguridad en data.table se hizo para evitar eso.