2013-02-09 7 views
9

Vorrei merge più data.frame in R utilizzando row.names, eseguendo un join esterno completo. Per questo speravo di fare quanto segue:unione di data.frame per riga in R

x = as.data.frame(t(data.frame(a=10, b=13, c=14))) 
y = as.data.frame(t(data.frame(a=1, b=2))) 
z = as.data.frame(t(data.frame(a=3, b=4, c=3, d=11))) 
res = Reduce(function(a,b) merge(a,b,by="row.names",all=T), list(x,y,z)) 

Warning message: 
In merge.data.frame(a, b, by = "row.names", all = T) : 
    column name ‘Row.names’ is duplicated in the result 
> res 
    Row.names Row.names V1.x V1.y V1 
    1   1   a 10 1 NA 
    2   2   b 13 2 NA 
    3   3   c 14 NA NA 
    4   a  <NA> NA NA 3 
    5   b  <NA> NA NA 4 
    6   c  <NA> NA NA 3 
    7   d  <NA> NA NA 11 

quello che speravo di ottenere sarebbe:

V1 V2 V3 
    a 10 1 3 
    b 13 2 4 
    c 14 NA 3 
    d NA NA 11 

risposta

6

I seguenti lavori (fino a qualche cambiamento titolo ultima colonna):

res <- Reduce(function(a,b){ 
     ans <- merge(a,b,by="row.names",all=T) 
     row.names(ans) <- ans[,"Row.names"] 
     ans[,!names(ans) %in% "Row.names"] 
     }, list(x,y,z)) 

Infatti:

> res 
    V1.x V1.y V1 
a 10 1 3 
b 13 2 4 
c 14 NA 3 
d NA NA 11 

Che cosa succede con una fila join è che una colonna con i rownames originali si aggiunge nella risposta, che a sua volta non contiene nomi di riga:

> merge(x,y,by="row.names",all=T) 
    Row.names V1.x V1.y 
1   a 10 1 
2   b 13 2 
3   c 14 NA 

Questo comportamento è documentato nella ?merge (in valore)

Se i corrispondenti nomi di riga coinvolti, una colonna di caratteri in più denominata Row.names viene aggiunta a sinistra e in tutti i casi il risultato è nomi di riga 'automatici'.

Quando Reduce tenta di unire nuovamente, non trova alcuna corrispondenza a meno che i nomi non vengano eliminati manualmente.

2

Per continuità, questa non è una soluzione pulita ma una soluzione alternativa, trasformo l'argomento dell'elenco di "Riduci" utilizzando sapply.

Reduce(function(a,b) merge(a,b,by=0,all=T), 
         sapply(list(x,y,z),rbind))[,-c(1,2)] 
    x y.x y.y 
1 10 1 3 
2 13 2 4 
3 14 NA 3 
4 NA NA 11 
Warning message: 
In merge.data.frame(a, b, by = 0, all = T) : 
    column name ‘Row.names’ is duplicated in the result 
0

Per qualche motivo non ho avuto molto successo con Reduce. dato un elenco di data.frames (df.lst) e un elenco di suffissi (suff.lst) per cambiare i nomi delle colonne identiche, questa è la mia soluzione (è un ciclo, so che è brutto per gli standard R, ma funziona) :

df.merg <- as.data.frame(df.lst[1]) 
colnames(df.merg)[-1] <- paste(colnames(df.merg)[-1],suff.lst[[1]],sep="") 
for (i in 2:length(df.lst)) { 
    df.i <- as.data.frame(df.lst[i]) 
    colnames(df.i)[-1] <- paste(colnames(df.i)[-1],suff.lst[[i]],sep="") 
    df.merg <- merge(df.merg, df.i, by.x="",by.y="", all=T) 
}