Почему allow.cartesian требуется в моменты, когда при подключении data.tables с дублирующими ключами?
Я пытаюсь понять логику поиска J(), когда есть дубликаты ключей в data.table в R.
Вот небольшой эксперимент, который я пробовал:
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,
Qaru and datatable-help for advice.
Я действительно не понимаю этого. Я знаю, что я должен избегать дублирования ключей в функции поиска, я просто хочу получить некоторое представление, поэтому я не буду делать никаких ошибок в будущем.
Спасибо за тонну за помощь. Это отличный инструмент.
Ответы
Ответ 1
Вам не нужно избегать дублирования ключей. Пока результат не будет больше, чем 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
привели к 3-кратному общему числу "a" в DT1
(= 1e7). Представьте, что если вы выполнили объединение с 1e4 значениями в DT2
, результаты будут взрываться! Чтобы избежать этого, есть аргумент allow.cartesian
, который по умолчанию FALSE.
Как я уже сказал, Мэтт однажды упомянул, что возможно просто предоставить ошибку в случае "больших" объединений (или объединений, что приводит к огромному количеству строк), которые могут быть установлены произвольно, я думаю). Это, когда/если будет реализовано, сделает соединение должным образом без этого сообщения об ошибке в случае соединений, которые не комбинаторно взрываются.
Ответ 2
+1 к тому, что сказал Арун. Я лично использовал dplyr для таких вещей в течение длительного времени, и простая опечатка (например, имя столбца в одном из кадров данных) во время соединения может привести к декартовому умножению с огромным результатом. Dplyr только начинает делать это, не проверяя, хватит ли на нем памяти, и в этот момент мой компьютер полностью застыл, и весь прогресс был потерян.
Эта мера безопасности в таблице данных была сделана для предотвращения этого.