307 votes

Combinez deux cadres de données par lignes (rbind) lorsqu'ils ont des ensembles de colonnes différents.

Est-il possible de lier en ligne deux cadres de données qui n'ont pas le même ensemble de colonnes ? J'espère pouvoir conserver les colonnes qui ne correspondent pas après la liaison.

271voto

rbind.fill du paquet plyr pourrait être ce que vous recherchez.

24 votes

rbind.fill et bind_rows() les deux abandonnent silencieusement les noms de domaine.

6 votes

@MERose Hadley : "Oui, toutes les méthodes dplyr ignorent les rownames".

0 votes

Voici un lien vers la documentation : rdocumentation.org/packages/plyr/versions/1.8.4/topics/

51voto

neilfws Points 3881

Vous pouvez utiliser smartbind de la gtools paquet.

Exemple :

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

3 votes

J'ai essayé smartbind avec deux grands cadres de données (au total environ 3*10^6 lignes) et l'a abandonné après 10 minutes.

3 votes

Beaucoup de choses se sont passées en 9 ans :) Il se peut que je n'utilise pas smartbind aujourd'hui. Notez également que la question originale ne spécifiait pas de grands cadres de données.

48voto

Aaron Statham Points 764

Si les colonnes dans df1 est un sous-ensemble de ceux de df2 (par les noms des colonnes) :

df3 <- rbind(df1, df2[, names(df1)])

23voto

Jonathan Chang Points 6231

Vous pouvez aussi vous contenter d'extraire les noms communs des colonnes.

> cols <- intersect(colnames(df1), colnames(df2))
> rbind(df1[,cols], df2[,cols])

8voto

Seth Points 1600

J'ai écrit une fonction pour faire cela parce que j'aime que mon code me dise si quelque chose ne va pas. Cette fonction vous dira explicitement quels noms de colonnes ne correspondent pas et si vous avez une incompatibilité de type. Ensuite, elle fera de son mieux pour combiner les data.frames de toute façon. La limitation est que vous ne pouvez combiner que deux data.frames à la fois.

### 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)
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X