¿Es posible enrutar dos marcos de datos que no tienen el mismo conjunto de columnas? Espero conservar las columnas que no coinciden después del enlace.Combina dos marcos de datos por filas (rbind) cuando tienen diferentes conjuntos de columnas
Respuesta
rbind.fill
del paquete plyr
podría ser lo que buscas.
Puede usar smartbind
del paquete gtools
.
Ejemplo:
library(gtools)
df1 <- data.frame(a = c(1:5), b = c(6:10))
df2 <- data.frame(a = c(11:15), b = c(16:20), c = LETTERS[1:5])
smartbind(df1, df2)
# result
a b c
1.1 1 6 <NA>
1.2 2 7 <NA>
1.3 3 8 <NA>
1.4 4 9 <NA>
1.5 5 10 <NA>
2.1 11 16 A
2.2 12 17 B
2.3 13 18 C
2.4 14 19 D
2.5 15 20 E
I tratado 'smartbind' con dos tramas de datos de gran tamaño (en total aproximadamente 3 * 10^6 filas) y abortada después de 10 minutos. – Joe
También puede simplemente sacar los nombres de las columnas comunes.
> cols <- intersect(colnames(df1), colnames(df2))
> rbind(df1[,cols], df2[,cols])
Si las columnas de gl1 es un subconjunto de los de gl2 (por nombres de columna):
df3 <- rbind(df1, df2[, names(df1)])
Tal vez leí mal por completo su pregunta, pero el "yo soy la esperanza de retener las columnas que no coinciden después del enlace "me hace pensar que estás buscando left join
o right join
similar a una consulta SQL. R tiene la función merge
que le permite especificar uniones izquierdas, derechas o internas similares a unir tablas en SQL.
Ya existe una gran pregunta y respuesta en este tema aquí: How to join (merge) data frames (inner, outer, left, right)?
escribí una función para hacer esto porque me gusta mi código para decirme si algo está mal. Esta función le indicará explícitamente qué nombres de columna no coinciden y si tiene un tipo no coincidente. Luego hará todo lo posible para combinar los data.frames de todos modos. La limitación es que solo puede combinar dos data.frames a la vez.
### combines data frames (like rbind) but by matching column names
# columns without matches in the other data frame are still combined
# but with NA in the rows corresponding to the data frame without
# the variable
# A warning is issued if there is a type mismatch between columns of
# the same name and an attempt is made to combine the columns
combineByName <- function(A,B) {
a.names <- names(A)
b.names <- names(B)
all.names <- union(a.names,b.names)
print(paste("Number of columns:",length(all.names)))
a.type <- NULL
for (i in 1:ncol(A)) {
a.type[i] <- typeof(A[,i])
}
b.type <- NULL
for (i in 1:ncol(B)) {
b.type[i] <- typeof(B[,i])
}
a_b.names <- names(A)[!names(A)%in%names(B)]
b_a.names <- names(B)[!names(B)%in%names(A)]
if (length(a_b.names)>0 | length(b_a.names)>0){
print("Columns in data frame A but not in data frame B:")
print(a_b.names)
print("Columns in data frame B but not in data frame A:")
print(b_a.names)
} else if(a.names==b.names & a.type==b.type){
C <- rbind(A,B)
return(C)
}
C <- list()
for(i in 1:length(all.names)) {
l.a <- all.names[i]%in%a.names
pos.a <- match(all.names[i],a.names)
typ.a <- a.type[pos.a]
l.b <- all.names[i]%in%b.names
pos.b <- match(all.names[i],b.names)
typ.b <- b.type[pos.b]
if(l.a & l.b) {
if(typ.a==typ.b) {
vec <- c(A[,pos.a],B[,pos.b])
} else {
warning(c("Type mismatch in variable named: ",all.names[i],"\n"))
vec <- try(c(A[,pos.a],B[,pos.b]))
}
} else if (l.a) {
vec <- c(A[,pos.a],rep(NA,nrow(B)))
} else {
vec <- c(rep(NA,nrow(A)),B[,pos.b])
}
C[[i]] <- vec
}
names(C) <- all.names
C <- as.data.frame(C)
return(C)
}
rbind.ordered=function(x,y){
diffCol = setdiff(colnames(x),colnames(y))
if (length(diffCol)>0){
cols=colnames(y)
for (i in 1:length(diffCol)) y=cbind(y,NA)
colnames(y)=c(cols,diffCol)
}
diffCol = setdiff(colnames(y),colnames(x))
if (length(diffCol)>0){
cols=colnames(x)
for (i in 1:length(diffCol)) x=cbind(x,NA)
colnames(x)=c(cols,diffCol)
}
return(rbind(x, y[, colnames(x)]))
}
gtools/aún no ha smartbind como trabajar con fechas, probablemente debido a que se as.vectoring. Así que aquí está mi solución ...
sbind = function(x, y, fill=NA) {
sbind.fill = function(d, cols){
for(c in cols)
d[[c]] = fill
d
}
x = sbind.fill(x, setdiff(names(y),names(x)))
y = sbind.fill(y, setdiff(names(x),names(y)))
rbind(x, y)
}
Una solución más reciente es el uso de dplyr
's bind_rows
función que yo supongo que es más eficiente que smartbind
.
Una alternativa con data.table
:
library(data.table)
df1 = data.frame(a = c(1:5), b = c(6:10))
df2 = data.frame(a = c(11:15), b = c(16:20), c = LETTERS[1:5])
rbindlist(list(df1, df2), fill = TRUE)
rbind
también funcionará en data.table
siempre que los objetos se convierten a data.table
objetos, por lo
rbind(setDT(df1), setDT(df2), fill=TRUE)
también trabajar en esta situación . Esto puede ser preferible cuando tiene un par de data.tables y no quiere construir una lista.
entiendo la pregunta:
a = data.frame(
x = c(1,2,3),
y = c(5,2,3)
)
b = data.frame(
u = c(6,2,3),
v = c(19,13,12)
)
dd=cbind(a, b)
str(dd)
'data.frame': 3 obs. of 4 variables:
$ x: num 1 2 3
$ y: num 5 2 3
$ u: num 6 2 3
$ v: num 19 13 12
Desafortunadamente, su comprensión parece incorrecta, como se puede ver al leer la respuesta aceptada. La pregunta es sobre * enlace de fila * dos marcos de datos en caso de que no tengan el mismo conjunto de columnas.Tu publicación trata sobre el enlace * column * usando 'cbind()'. Considere revisar su publicación con una respuesta única a la pregunta o eliminarla. Gracias. – Uwe
Sólo por la documentación.Puede probar el Stack
biblioteca y su función Stack
de la siguiente forma:
Stack(df_1, df_2)
también tengo la impresión de que es más rápido que otros métodos para grandes conjuntos de datos.
La mayoría de las respuestas de la base R abordan la situación donde solo un data.frame tiene columnas adicionales o que el data.frame resultante tendría la intersección de las columnas. Dado que el OP escribe espero conservar las columnas que no coinciden después del enlace, probablemente valga la pena publicar una respuesta utilizando los métodos de base R para abordar este problema.
A continuación, presento dos métodos de base R: uno que altera los data.frames originales y otro que no. Además, ofrezco un método que generaliza el método no destructivo a más de dos data.frames.
Primero, veamos algunos datos de muestra.
# sample data, variable c is in df1, variable d is in df2
df1 = data.frame(a=1:5, b=6:10, d=month.name[1:5])
df2 = data.frame(a=6:10, b=16:20, c = letters[8:12])
Dos data.frames, alteran originales
el fin de conservar todas las columnas de ambos data.frames en un rbind
(y permitir que la función de trabajar sin que se produzca un error), se agregue columnas NA a cada data.frame con los nombres faltantes correspondientes completados usando setdiff
.
# fill in non-overlapping columns with NAs
df1[setdiff(names(df2), names(df1))] <- NA
df2[setdiff(names(df1), names(df2))] <- NA
Ahora, rbind
-em
rbind(df1, df2)
a b d c
1 1 6 January <NA>
2 2 7 February <NA>
3 3 8 March <NA>
4 4 9 April <NA>
5 5 10 May <NA>
6 6 16 <NA> h
7 7 17 <NA> i
8 8 18 <NA> j
9 9 19 <NA> k
10 10 20 <NA> l
Tenga en cuenta que las dos primeras líneas alteran la data.frames original, DF1 y DF2, añadiendo el conjunto de columnas a ambos.
Dos data.frames, no alteran originales
Para dejar los originales intactos data.frames primer bucle, a través de los nombres que se diferencian, devuelve un vector con nombre de AN que se concatenan en una lista con el data.frame usando c
. Luego, data.frame
convierte el resultado en un data.frame apropiado para el rbind
.
rbind(
data.frame(c(df1, sapply(setdiff(names(df2), names(df1)), function(x) NA))),
data.frame(c(df2, sapply(setdiff(names(df1), names(df2)), function(x) NA)))
)
Muchos data.frames, no alteran originales
en el caso de que usted tiene más de dos data.frames, se puede hacer lo siguiente.
# put data.frames into list (dfs named df1, df2, df3, etc)
mydflist <- mget(ls(pattern="df\\d+")
# get all variable names
allNms <- unique(unlist(lapply(mydflist, names)))
# put em all together
do.call(rbind,
lapply(mydflist,
function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
function(y) NA)))))
Tal vez un poco mejor no ver los nombres de las filas de data.frames originales? Entonces haz esto.
do.call(rbind,
c(lapply(mydflist,
function(x) data.frame(c(x, sapply(setdiff(allNms, names(x)),
function(y) NA)))),
make.row.names=FALSE))
- 1. Pegar columnas de dos marcos de datos
- 2. ¿Cómo combino dos marcos de datos basados en dos columnas?
- 3. Aplicar sobre dos marcos de datos
- 4. Combinar dos marcos de datos y eliminar columnas duplicadas
- 5. Fusionar marcos de datos sin duplicar filas
- 6. set_intersection para dos tipos diferentes de conjuntos
- 7. dos leyendas basadas en diferentes conjuntos de datos con ggplot2
- 8. Compruebe si dos variables tienen valores de dos conjuntos diferentes, el modo DRY
- 9. Mysql Seleccione Filas Cuando dos columnas no tienen el mismo valor
- 10. R: cómo enlazar dos enormes marcos de datos sin quedarse sin memoria
- 11. ¿Cómo comparar dos marcos de datos?
- 12. ¿Qué sucede cuando dos anotaciones diferentes tienen el mismo nombre?
- 13. Cómo enlazar solo las columnas comunes de dos conjuntos de datos
- 14. Agregar dos marcos de datos de pandas
- 15. Intersección de dos conjuntos (Listas) de datos
- 16. Proceso para comparar dos conjuntos de datos
- 17. seleccionar filas con Max Valor agrupadas por dos columnas
- 18. Fusionando dos marcos de datos en R que tienen muestras comunes y poco comunes
- 19. orden SQL por dos columnas diferentes (posiblemente nulas)
- 20. ¿Cómo obtengo el número de filas que tienen columnas duplicadas?
- 21. ¿Por qué Asp.net MVC no puede distinguir entre dos acciones cuando tienen diferentes parámetros?
- 22. seleccionar * de dos mesas con diferentes # de columnas
- 23. Combinar múltiples conjuntos de filas en SPARQL
- 24. Comparación de filas entre dos matrices
- 25. ¿Cómo contar las filas que tienen los mismos valores en dos columnas (SQL)?
- 26. Combina dos variables de fecha y hora en una
- 27. seleccionar filas que tienen 2 columnas igual valor
- 28. rbind dataframes en una lista de listas
- 29. Overplotting desde diferentes marcos de datos en ggplot2
- 30. MySQL compara dos tablas y devuelve filas que tienen la misma clave principal pero datos diferentes en otros campos
'rbind.fill' y' bind_rows() 'ambos colocan rownames en forma silenciosa. – MERose
@MOSE Hadley: "Sí, todos los métodos dplyr ignoran nombres de fila". – zx8754