Esta es una pregunta un poco filosófica sobre la sintaxis de unión de data.table. Estoy encontrando cada vez más usos para data.tables, pero sigo aprendiendo ...
El formato X[Y]
de combinación para data.tables es muy conciso, práctico y eficiente, pero hasta donde yo sé, solo admite combinaciones internas y combinaciones externas derechas. Para obtener una combinación externa izquierda o completa, necesito usar merge
:
X[Y, nomatch = NA]
- todas las filas en Y - unión externa derecha (predeterminado)X[Y, nomatch = 0]
- solo filas con coincidencias tanto en X como en Y - unión internamerge(X, Y, all = TRUE)
- todas las filas de X e Y - unión externa completamerge(X, Y, all.x = TRUE)
- todas las filas en X - unión exterior izquierda
Me parece que sería útil si el X[Y]
formato de combinación admitiera los 4 tipos de combinaciones. ¿Hay alguna razón por la que solo se admiten dos tipos de combinaciones?
Para mí, los valores de los parámetros nomatch = 0
y nomatch = NA
no son muy intuitivos para las acciones que se realizan. Es más fácil para mí entender y recordar la merge
sintaxis: all = TRUE
, all.x = TRUE
y all.y = TRUE
. Dado que la X[Y]
operación se parece merge
mucho más a match
, ¿por qué no usar la merge
sintaxis para las combinaciones en lugar match
del nomatch
parámetro de la función ?
Aquí hay ejemplos de código de los 4 tipos de combinación:
# sample X and Y data.tables
library(data.table)
X <- data.table(t = 1:4, a = (1:4)^2)
setkey(X, t)
X
# t a
# 1: 1 1
# 2: 2 4
# 3: 3 9
# 4: 4 16
Y <- data.table(t = 3:6, b = (3:6)^2)
setkey(Y, t)
Y
# t b
# 1: 3 9
# 2: 4 16
# 3: 5 25
# 4: 6 36
# all rows from Y - right outer join
X[Y] # default
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
X[Y, nomatch = NA] # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
merge(X, Y, by = "t", all.y = TRUE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
# 3: 5 NA 25
# 4: 6 NA 36
identical(X[Y], merge(X, Y, by = "t", all.y = TRUE))
# [1] TRUE
# only rows in both X and Y - inner join
X[Y, nomatch = 0]
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t") # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
merge(X, Y, by = "t", all = FALSE) # same as above
# t a b
# 1: 3 9 9
# 2: 4 16 16
identical( X[Y, nomatch = 0], merge(X, Y, by = "t", all = FALSE) )
# [1] TRUE
# all rows from X - left outer join
merge(X, Y, by = "t", all.x = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# all rows from both X and Y - full outer join
merge(X, Y, by = "t", all = TRUE)
# t a b
# 1: 1 1 NA
# 2: 2 4 NA
# 3: 3 9 9
# 4: 4 16 16
# 5: 5 NA 25
# 6: 6 NA 36
Actualización: data.table v1.9.6 introdujo la on=
sintaxis, que permite combinaciones ad hoc en campos distintos a la clave principal. La respuesta de jangorecki a la pregunta ¿Cómo unir (fusionar) marcos de datos (interno, externo, izquierdo, derecho)? proporciona algunos ejemplos de tipos de combinación adicionales que puede manejar data.table.
fuente
Y[X]
si desea la combinación externa izquierda deX[Y]
yrbind(Y[X],X[Y])
si desea una combinación externa completaunique()
enfoque a continuación para la combinación completa es preferiblerbind(Y[X],X[Y])
, ya que el rbind implicaría copiar la tabla. ¿Está bien?unique(c(unique(X[,t]), unique(Y[,t]))
, esto debería ser más eficiente en memoria, ya que solo combina dos listas que serán menores o iguales que la cantidad de filas en X e Y .Respuestas:
Para citar las
data.table
preguntas frecuentes 1.11 ¿Cuál es la diferencia entreX[Y]
ymerge(X, Y)
?Si desea una combinación externa izquierda de
X[Y]
Si quieres una combinación externa completa
fuente
X[Y,all=T]
podría ser una forma elegante de especificar una combinación externa completa dentro de la sintaxis data.table X [Y]. OX[Y,all.x=T]
para la unión de la izquierda. Me pregunté por qué no estaba diseñado de esa manera. Solo un pensamiento.X[Y[J(unique_keys)]]
?La respuesta de @ mnel es acertada, así que acepta esa respuesta. Esto es solo un seguimiento, demasiado largo para comentarios.
Como dice mnel, la unión externa izquierda / derecha se obtiene intercambiando
Y
yX
:Y[X]
-vs-X[Y]
. Entonces, 3 de los 4 tipos de combinación son compatibles con esa sintaxis, no 2, iiuc.Agregar el cuarto parece una buena idea. Digamos que agregamos
full=TRUE
oboth=TRUE
omerge=TRUE
(¿no está seguro del mejor nombre de argumento?) Entonces no se me había ocurrido antes queX[Y,j,merge=TRUE]
sería útil por las razones posteriores al PERO en la pregunta frecuente 1.12. Nueva solicitud de función ahora agregada y vinculada aquí, gracias:FR # 2301: Agregue el argumento merge = TRUE para las uniones X [Y] e Y [X] como lo hace merge ().
Las versiones recientes se han acelerado
merge.data.table
(al tomar una copia superficial internamente para configurar las claves de manera más eficiente, por ejemplo). Así que estamos tratando de llevarmerge()
yX[Y]
más cerca, y proporcionar a todas las opciones de usuario para una flexibilidad total. Ambos tienen pros y contras. Otra solicitud de función destacada es:FR # 2033: Agregue by.xy by.y a merge.data.table
Si hay otros, por favor sigan viniendo.
Por esta parte de la pregunta:
Si prefiere
merge()
sintaxis y sus 3 argumentosall
,all.x
yall.y
entonces sólo tiene que utilizar que en lugar deX[Y]
. Creo que debería cubrir todos los casos. ¿O quieres decir qué es el argumento de un solonomatch
en[.data.table
? Si es así, es la forma que parecía natural dada la pregunta frecuente 2.14: "¿Puede explicar más por qué data.table se inspira en la sintaxis A [B] en base?". Pero además,nomatch
solo toma dos valores actualmente0
yNA
. Eso podría extenderse para que un valor negativo signifique algo, o 12 significaría usar los valores de la 12ª fila para completar NA, por ejemplo, onomatch
en el futuro podría ser un vector o incluso él mismo adata.table
.Hm. ¿Cómo interactuaría by-without-by con merge = TRUE? Quizás deberíamos llevar esto a datatable-help .
fuente
join="all", join="all.x", join="all.y" and join="x.and.y"
en el margen de mis notas. No estoy seguro si eso es mejor.join
así, buena idea. Publiqué en datatable-help, así que veamos. Quizás también dédata.table
algo de tiempo para acomodarse. ¿Ha llegado a by-without-by todavía, por ejemplo, y se ha unido al alcance heredado ?join
palabra clave para, cuando i es una tabla de datos:X[Y,j,join=string]
. Se sugiere que los posibles valores de cadena para la combinación sean: 1) "all.y" y "right" -Esta "respuesta" es una propuesta para la discusión: Como se indica en mi comentario, yo sugiero agregar un
join
parámetro a [.data.table () para permitir que otros tipos de uniones, es decir:X[Y,j,join=string]
. Además de los 4 tipos de combinaciones ordinarias, también sugiero admitir 3 tipos de combinaciones exclusivas y la combinación cruzada .Se
join
propone que los valores de cadena (y alias) para los distintos tipos de combinación sean:"all.y"
y"right"
- combinación derecha, la tabla de datos actual predeterminada (nomatch = NA) - todas las filas Y con NA donde no hay coincidencia X;"both"
y"inner"
- unión interna (nomatch = 0) - solo filas donde X e Y coinciden;"all.x"
y"left"
- unión a la izquierda - todas las filas de X, NA donde no coincide Y:"outer"
y"full"
- unión externa completa - todas las filas de X e Y, NA donde no coinciden"only.x"
y"not.y"
- filas X que no se unen o que no se unen y que regresan donde no hay coincidencia de Y"only.y"
y"not.x"
- filas Y de retorno no unidas o anti-unión donde no hay coincidencia X"not.both"
- combinación exclusiva que devuelve filas X e Y donde no hay coincidencia con la otra tabla, es decir, una exclusiva-o (XOR)"cross"
- unión cruzada o producto cartesiano con cada fila de X emparejada con cada fila de YEl valor predeterminado es el
join="all.y"
que corresponde al valor predeterminado actual.Los valores de cadena "all", "all.x" y "all.y" corresponden a
merge()
parámetros. Las cadenas "derecha", "izquierda", "interna" y "externa" pueden ser más adecuadas para los usuarios de SQL.Las cadenas "both" y "not.both" son mi mejor sugerencia en este momento, pero alguien puede tener mejores sugerencias de cadenas para la combinación interna y la combinación exclusiva. (No estoy seguro de si "exclusivo" es la terminología correcta, corrígeme si existe un término adecuado para una unión "XOR").
El uso de
join="not.y"
es una alternativa para la sintaxis de combinaciónX[-Y,j]
oX[!Y,j]
no y tal vez más claro (para mí), aunque no estoy seguro de si son lo mismo (nueva característica en data.table versión 1.8.3).La unión cruzada puede ser útil a veces, pero puede que no encaje en el paradigma data.table.
fuente
join
pero a menos que llegue al rastreador, se olvidará.