Cómo unir (fusionar) marcos de datos (interior, exterior, izquierda, derecha)
Dados dos marcos de datos:
df1 = data.frame(CustomerId = c(1:6), Product = c(rep("Toaster", 3), rep("Radio", 3)))
df2 = data.frame(CustomerId = c(2, 4, 6), State = c(rep("Alabama", 2), rep("Ohio", 1)))
df1
# CustomerId Product
# 1 Toaster
# 2 Toaster
# 3 Toaster
# 4 Radio
# 5 Radio
# 6 Radio
df2
# CustomerId State
# 2 Alabama
# 4 Alabama
# 6 Ohio
¿Cómo puedo unir el estilo de la base de datos, es decir, el estilo SQL ? Es decir, ¿cómo consigo:
- Una combinación interna de
df1
ydf2
:
Devuelve solo las filas en las que la tabla de la izquierda tiene claves coincidentes en la tabla de la derecha. - Una combinación externa de
df1
ydf2
:
devuelve todas las filas de ambas tablas, une los registros de la izquierda que tienen claves coincidentes en la tabla de la derecha. - Una combinación externa izquierda (o simplemente una combinación izquierda) de
df1
ydf2
Devuelve todas las filas de la tabla de la izquierda y cualquier fila con claves coincidentes de la tabla de la derecha. - Una combinación externa derecha de
df1
ydf2
Devuelve todas las filas de la tabla derecha y cualquier fila con claves coincidentes de la tabla izquierda.
Crédito adicional:
¿Cómo puedo hacer una declaración de selección de estilo SQL?
Usando la merge
función y sus parámetros opcionales:
Unión interna: merge(df1, df2)
funcionará para estos ejemplos porque R une automáticamente los marcos mediante nombres de variables comunes, pero lo más probable es que desee especificarlomerge(df1, df2, by = "CustomerId")
para asegurarse de que coincida solo en los campos que desea. También puede utilizar losby.x
yby.y
si las variables coincidentes tienen nombres diferentes en los diferentes marcos de datos.
Unión externa: merge(x = df1, y = df2, by = "CustomerId", all = TRUE)
Exterior izquierdo: merge(x = df1, y = df2, by = "CustomerId", all.x = TRUE)
Exterior derecho: merge(x = df1, y = df2, by = "CustomerId", all.y = TRUE)
Unión cruzada: merge(x = df1, y = df2, by = NULL)
Al igual que con la combinación interna, probablemente desee pasar explícitamente "CustomerId" a R como variable coincidente. Creo que casi siempre es mejor indicar explícitamente los identificadores que desea fusionar; Es más seguro si los marcos de datos de entrada cambian inesperadamente y son más fáciles de leer más adelante.
Puede fusionar varias columnas proporcionando by
un vector, por ejemplo, by = c("CustomerId", "OrderId")
.
Si los nombres de las columnas a fusionar no son los mismos, puede especificar, por ejemplo, by.x = "CustomerId_in_df1", by.y = "CustomerId_in_df2"
dónde CustomerId_in_df1
está el nombre de la columna en el primer marco de datos y dónde CustomerId_in_df2
está el nombre de la columna en el segundo marco de datos. (Estos también pueden ser vectores si necesita fusionar varias columnas).
Recomendaría consultar el paquete sqldf de Gabor Grothendieck , que le permite expresar estas operaciones en SQL.
library(sqldf)
## inner join
df3 <- sqldf("SELECT CustomerId, Product, State
FROM df1
JOIN df2 USING(CustomerID)")
## left join (substitute 'right' for right join)
df4 <- sqldf("SELECT CustomerId, Product, State
FROM df1
LEFT JOIN df2 USING(CustomerID)")
Considero que la sintaxis de SQL es más simple y natural que su equivalente en R (pero esto puede reflejar mi preferencia por RDBMS).
Consulte sqldf GitHub de Gabor para obtener más información sobre las uniones.
También puedes hacer uniones usando el increíble paquete dplyr de Hadley Wickham .
library(dplyr)
#make sure that CustomerId cols are both the same type
#they aren’t in the provided data (one is integer and one is double)
df1$CustomerId <- as.double(df1$CustomerId)
Uniones mutantes: agregue columnas a df1 usando coincidencias en df2
#inner
inner_join(df1, df2)
#left outer
left_join(df1, df2)
#right outer
right_join(df1, df2)
#alternate right outer
left_join(df2, df1)
#full join
full_join(df1, df2)
Filtrado de uniones: filtre filas en df1, no modifique columnas
#keep only observations in df1 that match in df2.
semi_join(df1, df2)
#drop all observations in df1 that match in df2.
anti_join(df1, df2)
Existe el enfoque data.table para una unión interna, que es muy eficiente en tiempo y memoria (y necesario para algunos marcos de datos más grandes):
library(data.table)
dt1 <- data.table(df1, key = "CustomerId")
dt2 <- data.table(df2, key = "CustomerId")
joined.dt1.dt.2 <- dt1[dt2]
merge
también funciona en data.tables (ya que es genérico y llama merge.data.table
)
merge(dt1, dt2)
data.table documentado en stackoverflow:
Cómo hacer una operación de fusión de data.table
Traducir uniones SQL en claves externas a la sintaxis de R data.table
Alternativas eficientes para fusionar para data.frames más grandes R
Cómo hacer una unión externa izquierda básica con data.table en R?
Otra opción más es la join
función que se encuentra en el paquete plyr . [Nota de 2022: plyr ya está retirado y ha sido reemplazado por dplyr . Las operaciones de unión en dplyr se describen en esta respuesta .]
library(plyr)
join(df1, df2,
type = "inner")
# CustomerId Product State
# 1 2 Toaster Alabama
# 2 4 Radio Alabama
# 3 6 Radio Ohio
Opciones para type
: inner
, left
, right
, full
.
De ?join
: A diferencia de merge
, [ join
] conserva el orden de x sin importar qué tipo de combinación se utilice.
Hay algunos buenos ejemplos de cómo hacer esto en R Wiki . Robaré un par aquí:
Método de fusión
Dado que sus claves tienen el mismo nombre, la forma corta de realizar una unión interna es fusionar():
merge(df1, df2)
Se puede crear una combinación interna completa (todos los registros de ambas tablas) con la palabra clave "todos":
merge(df1, df2, all=TRUE)
una unión exterior izquierda de df1 y df2:
merge(df1, df2, all.x=TRUE)
una unión exterior derecha de df1 y df2:
merge(df1, df2, all.y=TRUE)
puedes darles la vuelta, darles una bofetada y frotarlas para obtener las otras dos uniones exteriores sobre las que preguntaste :)
Método de subíndice
Una unión externa izquierda con df1 a la izquierda usando un método de subíndice sería:
df1[,"State"]<-df2[df1[ ,"Product"], "State"]
La otra combinación de uniones externas se puede crear mezclando el ejemplo del subíndice de unión externa izquierda. (sí, sé que eso equivale a decir "lo dejaré como ejercicio para el lector...")