Tengo una lista de muchos data.frames que quiero fusionar. El problema aquí es que cada data.frame difiere en términos del número de filas y columnas, pero todos comparten las variables clave (que he llamado "var1"
y "var2"
en el código a continuación). Si los data.frames fueran idénticos en términos de columnas, podría simplemente rbind
, para lo cual rbind.fill de plyr haría el trabajo, pero ese no es el caso con estos datos.
Debido a que el merge
comando solo funciona en 2 data.frames, recurrí a Internet para obtener ideas. Obtuve este de aquí , que funcionó perfectamente en R 2.7.2, que es lo que tenía en ese momento:
merge.rec <- function(.list, ...){
if(length(.list)==1) return(.list[[1]])
Recall(c(list(merge(.list[[1]], .list[[2]], ...)), .list[-(1:2)]), ...)
}
Y llamaría a la función así:
df <- merge.rec(my.list, by.x = c("var1", "var2"),
by.y = c("var1", "var2"), all = T, suffixes=c("", ""))
Pero en cualquier versión R posterior a 2.7.2, incluidas 2.11 y 2.12, este código falla con el siguiente error:
Error in match.names(clabs, names(xi)) :
names do not match previous names
(Incidentalmente, veo otras referencias a este error en otra parte sin resolución).
¿Hay alguna forma de resolver esto?
map_dfr()
omap_dfc()
dfs = [df1, df2, df3]
entoncesreduce(pandas.merge, dfs)
.Reducir hace esto bastante fácil:
Aquí hay un ejemplo completo usando algunos datos simulados:
Y aquí hay un ejemplo usando estos datos para replicar
my.list
:Nota: Parece que esto podría decirse que es un error
merge
. El problema es que no hay verificación de que agregar los sufijos (para manejar nombres superpuestos no coincidentes) los haga únicos. En un momento determinado se utiliza[.data.frame
la cual hacemake.unique
los nombres, haciendo que larbind
falle.La forma más fácil de solucionarlo es no dejar el campo renombrando campos duplicados (de los cuales hay muchos aquí)
merge
. P.ej:El
merge
/Reduce
entonces funcionará bien.fuente
empty <- data.frame(x=numeric(0),a=numeric(0); L3 <- c(empty,empty,list.of.data.frames,empty,empty,empty)
y sucedieron algunas cosas extrañas que aún no he descubierto.Puedes hacerlo usando
merge_all
elreshape
paquete. Puede pasar parámetros paramerge
usar el...
argumentoAquí hay un excelente recurso sobre diferentes métodos para fusionar marcos de datos .
fuente
Puedes usar la recursión para hacer esto. No he verificado lo siguiente, pero debería darte la idea correcta:
fuente
Reutilizaré el ejemplo de datos de @PaulRougieux
Aquí hay una solución corta y dulce usando
purrr
ytidyr
fuente
La función
eat
de mi paquete safejoin tiene esa característica, si le da una lista de data.frames como una segunda entrada, los unirá recursivamente a la primera entrada.Pedir prestado y ampliar los datos de la respuesta aceptada:
No tenemos que tomar todas las columnas, podemos usar ayudantes seleccionados de tidyselect y elegir (a medida que comenzamos desde que se mantienen
.x
todas las.x
columnas):o eliminar los específicos:
Si se nombra la lista, los nombres se utilizarán como prefijos:
Si hay conflictos de columna, el
.conflict
argumento le permite resolverlo, por ejemplo, tomando el primero / segundo, agregándolos, fusionándolos o anidándolos.mantener primero:
mantener el último:
añadir:
juntarse:
nido:
NA
los valores se pueden reemplazar usando el.fill
argumentoDe manera predeterminada, es una opción mejorada,
left_join
pero todas las uniones dplyr son compatibles con el.mode
argumento, las uniones difusas también son compatibles con elmatch_fun
argumento (está envuelto alrededor del paquetefuzzyjoin
) o dan una fórmula como~ X("var1") > Y("var2") & X("var3") < Y("var4")
la delby
argumento.fuente
Tenía una lista de marcos de datos sin columna de identificación común.
Me faltaban datos en muchos dfs. Había valores nulos. Los marcos de datos se produjeron utilizando la función de tabla. Reducir, Fusionar, rbind, rbind.fill y sus similares no pudieron ayudarme a lograr mi objetivo. Mi objetivo era producir un marco de datos combinado comprensible, irrelevante de los datos faltantes y la columna de identificación común.
Por lo tanto, hice la siguiente función. Quizás esta función pueda ayudar a alguien.
está siguiendo la función
Ejecutando el ejemplo
fuente
Cuando tiene una lista de dfs, y una columna contiene la "ID", pero en algunas listas faltan algunas ID, entonces puede usar esta versión de Reducir / Fusionar para unir múltiples Dfs de ID o etiquetas de fila faltantes:
fuente
Aquí hay un contenedor genérico que se puede usar para convertir una función binaria en función de parámetros múltiples. El beneficio de esta solución es que es muy genérico y se puede aplicar a cualquier función binaria. Solo necesita hacerlo una vez y luego puede aplicarlo en cualquier lugar.
Para demostrar la idea, utilizo una recursión simple para implementar. Por supuesto, se puede implementar de una manera más elegante que se beneficie del buen soporte de R para el paradigma funcional.
Luego puede simplemente envolver cualquier función binaria con él y llamar con parámetros posicionales (generalmente data.frames) en los primeros paréntesis y parámetros con nombre en los segundos paréntesis (como
by =
osuffix =
). Si no hay parámetros con nombre, deje los segundos paréntesis vacíos.fuente