Para unir data.frames
en R existe la función merge
que con todas sus opciones hace que esto sea una tarea fácil, sin embargo, se vuelve una tarea aburrida y repetitiva cuando se tienen muchos data.frames
para unir, puesto que la función merge
solo permite la unión de dos a la vez, véase la definición de los argumentos y la ayuda de dicha función. Pese a este inconveniente, la función merge
puede ser utilizada para unir tantos data.frames
como queramos si la combinamos apropiadamente con la función Reduce
, el único requisito que se ha de tener en cuenta es que el nombre de la variable identificadora sea el mismo en todos los data.frames
a ser unidos. Vemos unos ejemplos.
Consideremos los siguientes data.frames:
A <- data.frame(id = c("A", "B", "C", "D"), age = c(24, 25, 17, 19), height = c(1.8,
1.9, 1.75, 1.65))
A
## id age height
## 1 A 24 1.80
## 2 B 25 1.90
## 3 C 17 1.75
## 4 D 19 1.65
B <- data.frame(gender = c("M", "M", "F", "F"), id = c("A", "B", "C", "D"))
B
## gender id
## 1 M A
## 2 M B
## 3 F C
## 4 F D
C <- data.frame(id = c("A", "B", "C", "D"), math = c(6.5, 8.9, 7.4, 9.2), science = c(7.2,
8.4, 6.5, 8.7))
C
## id math science
## 1 A 6.5 7.2
## 2 B 8.9 8.4
## 3 C 7.4 6.5
## 4 D 9.2 8.7
D <- data.frame(id = c("A", "B", "C", "D"), eyes = c("blue", "brown", "green",
"black"))
C
## id math science
## 1 A 6.5 7.2
## 2 B 8.9 8.4
## 3 C 7.4 6.5
## 4 D 9.2 8.7
# Nótese que todos ellos tienen como variable identificadora id
## Uniendo los dataframes con merge
AB <- merge(A, B) # une A con B
ABC <- merge(AB, C) # a la unión de A y B le agrega C
ABCD <- merge(ABC, D) # a la unión de A, B y C le agrega D
ABCD # resultado final
## id age height gender math science eyes
## 1 A 24 1.80 M 6.5 7.2 blue
## 2 B 25 1.90 M 8.9 8.4 brown
## 3 C 17 1.75 F 7.4 6.5 green
## 4 D 19 1.65 F 9.2 8.7 black
Como se ha visto, se tiene que ir uniendo dos data.frames
en cada paso. ¿Hay alguna manera de hacerlo en un sólo paso? La respuesta es Sí y sólo requiere combinar la función merge
con Reduce
y tener en cuenta que la variable identificadora en cada data.frame
tenga el mismo nombre (id
en este ejemplo), no hace falta que esta variable ocupe la misma posición en cada data.frame
, sólo se requiere que sea nombrada de la misma manera. El ejemplo anterior se puede hacer tan sólo con una simple linea de comandos:
Reduce(merge, list(A, B, C, D))
## id age height gender math science eyes
## 1 A 24 1.80 M 6.5 7.2 blue
## 2 B 25 1.90 M 8.9 8.4 brown
## 3 C 17 1.75 F 7.4 6.5 green
## 4 D 19 1.65 F 9.2 8.7 black
Como se ve en ambos casos se obtiene el mismo resultado, sin embargo en el segundo, se ha hecho todo de una vez.
Otro ejemplo:
authors <- data.frame(surname = I(c("Tukey", "Venables", "Tierney", "Ripley",
"McNeil")), nationality = c("US", "Australia", "US", "UK", "Australia"),
deceased = c("yes", rep("no", 4)))
books <- data.frame(name = I(c("Tukey", "Venables", "Tierney", "Ripley", "Ripley",
"McNeil", "R Core")), title = c("Exploratory Data Analysis", "Modern Applied Statistics ...",
"LISP-STAT", "Spatial Statistics", "Stochastic Simulation", "Interactive Data Analysis",
"An Introduction to R"), other.author = c(NA, "Ripley", NA, NA, NA, NA,
"Venables & Smith"))
colnames(authors)[1] <- "name" # cambiando el ID de authors para que sea igual para todos
edition <- data.frame(name = authors[, 1], edition = c(4, 2, 3, 1, 2)) # invento
year <- data.frame(name = authors[, 1], year = 2000:2004) # invento
Los data.frames authors
y books
son los ejemplos que se encuentran en la ayuda de merge',
editiony
year fueron inventos míos para ilustrar el ejemplo.
Uniendo los data.frames
usando merge
, dos a la vez.
m1 <- merge(authors, books)
m2 <- merge(m1, edition)
(m3 <- merge(m2, year)) # El resultado final es:
## name nationality deceased title other.author
## 1 McNeil Australia no Interactive Data Analysis <NA>
## 2 Ripley UK no Spatial Statistics <NA>
## 3 Ripley UK no Stochastic Simulation <NA>
## 4 Tierney US no LISP-STAT <NA>
## 5 Tukey US yes Exploratory Data Analysis <NA>
## 6 Venables Australia no Modern Applied Statistics ... Ripley
## edition year
## 1 2 2004
## 2 1 2003
## 3 1 2003
## 4 3 2002
## 5 4 2000
## 6 2 2001
Uniéndolos todos a la vez:
Reduce(merge, list(authors, books, edition, year))
## name nationality deceased title other.author
## 1 McNeil Australia no Interactive Data Analysis <NA>
## 2 Ripley UK no Spatial Statistics <NA>
## 3 Ripley UK no Stochastic Simulation <NA>
## 4 Tierney US no LISP-STAT <NA>
## 5 Tukey US yes Exploratory Data Analysis <NA>
## 6 Venables Australia no Modern Applied Statistics ... Ripley
## edition year
## 1 2 2004
## 2 1 2003
## 3 1 2003
## 4 3 2002
## 5 4 2000
## 6 2 2001
Como se ha visto, si se combina merge
con Reduce
se pueden unir tantos data.frames
en un sólo paso, sin embargo, con el enfoque tradicional de usar sólo merge
se tiene que repetir la operación \( K-1 \) veces donde \( K \) es el número de data.frames
.
Justo lo que necesitaba, me habían recomendado ya buscar la función merge, pero la combinación con reduce me va a venor fenomenal.
ResponderEliminarMuchas gracias
esta bien. aunque eso mismo se haría en excel muy rápidamente. algo que si me parece interesante y que no puede hacer con excel fácilmente es usar merge para combinar dos tablas con tamaños diferentes.
ResponderEliminarPodrias hacer un tutorial usando by.x y by.y para combinar data.frames?
Se puede hacer, pero no precisamente con un merge.
EliminarY como lo hariamos si... Por ejemplo, tuvimos que particionar una base de datos en excel por su tamaño, pero queremos consolidarla para dejarla como maestra y usarla en R...???
ResponderEliminarEsta vez no agregando variables, si no que información (filas)
Gracias.
Muy amable ;)
ResponderEliminarcómo se podrían juntar bases con distinto número de observaciones, pero igual variables?
ResponderEliminarcomo se pueden cruzar varias bases de datos, que conserve el tamaño de la base de datos más grande y que no sume los otros registros. Por ejemplo, que en una base aparezca, id más nombre, id mas color de ojos, id más estatura, pero que cada base no tienen los mismos No. de id, sino diferentes pero que me traiga las variables de estatura, color de ojos ,nombre de la id, que solo aparezca en la base de datos grande, y que si no esta esa id en la base de datos más grande, no me sume las que no estan ahi, pero si en las otras bases de datos. Gracias.
ResponderEliminar