2013-10-10 12 views
34

Questo è venuto solo in una risposta ad un'altra domanda qui. Quando si rbind due frame di dati, esso corrisponde colonne in base al nome, piuttosto che di indice, che può portare a un comportamento imprevisto:Il modo più semplice per ottenere da rbind di ignorare i nomi delle colonne

> df<-data.frame(x=1:2,y=3:4) 
> df 
    x y 
1 1 3 
2 2 4 
> rbind(df,df[,2:1]) 
    x y 
1 1 3 
2 2 4 
3 1 3 
4 2 4 

Naturalmente, ci sono soluzioni alternative. Per esempio:

rbind(df,rename(df[,2:1],names(df))) 
data.frame(rbind(as.matrix(df),as.matrix(df[,2:1]))) 

su Edit: rename dal pacchetto plyr in realtà non funziona in questo modo (anche se ho pensato che avevo a lavorare quando ho originariamente scritto questo ...). Il modo per farlo rinominando è quello di utilizzare la soluzione di SimonO101:

rbind(df,setNames(df[,2:1],names(df))) 

Inoltre, forse sorprendentemente,

data.frame(rbindlist(list(df,df[,2:1]))) 

opere di indice (e se non ci importa una tabella di dati, quindi è piuttosto conciso), quindi questa è una differenza tra do.call(rbind).

La domanda è, qual è il modo più conciso per rbind due frame di dati in cui i nomi non corrispondono? So che questo sembra banale, ma questo genere di cose può finire per ingombrare il codice. E non voglio dover scrivere una nuova funzione chiamata rbindByIndex. Idealmente sarebbe qualcosa come rbind(df,df[,2:1],byIndex=T).

+2

Interessante. Sebbene personalmente preferirei che 'rbind' sui dataframes si occupino di far corrispondere i sottoinsiemi denominati (cioè le colonne). Quando non vuoi "tracciare" le cose per nome, usa 'matrix' in primo luogo? –

+0

Uno (forse l'unico) motivo per non utilizzare 'matrix' è perché non consente il mix di tipi. – mrip

risposta

36

Si potrebbe trovare setNames utile qui ...

rbind(df, setNames(rev(df), names(df))) 
# x y 
#1 1 3 
#2 2 4 
#3 3 1 
#4 4 2 

ho il sospetto il tuo vero caso d'uso è un po 'più complesso. Naturalmente puoi riordinare le colonne nel primo argomento di setNames come desideri, basta usare names(df) nel secondo argomento, in modo che i nomi delle colonne riordinate corrispondano all'originale.

+0

+1 Nizza. Vorrei aver saputo di questo prima. – Thomas

+0

Grazie, stavo usando 'rename' dal pacchetto' plyr', e ora quando provo a rieseguire il mio codice dall'OP, non funziona. – mrip

+0

@Thomas si, è una funzione davvero molto utile! –

7

Questo sembra abbastanza semplice:

mapply(c,df,df[,2:1]) 
    x y 
[1,] 1 3 
[2,] 2 4 
[3,] 3 1 
[4,] 4 2 

Per questo semplice caso, però, è necessario riattivarlo in un dataframe (perché mapply semplifica ad una matrice):

as.data.frame(mapply(c,df,df[,2:1])) 
    x y 
1 1 3 
2 2 4 
3 3 1 
4 4 2 

Nota importante 1: sembra esserci uno svantaggio della coercizione di tipo quando il dataframe contiene vettori di tipi diversi:

df<-data.frame(x=1:2,y=3:4,z=c('a','b')) 
mapply(c,df,df[,c(2:1,3)]) 
    x y z 
[1,] 1 3 2 
[2,] 2 4 1 
[3,] 3 1 2 
[4,] 4 2 1 

Nota importante 2: È anche terribile se si dispone di fattori.

df<-data.frame(x=factor(1:2),y=factor(3:4)) 
mapply(c,df[,1:2],df[,2:1]) 
    x y 
[1,] 1 1 
[2,] 2 2 
[3,] 1 1 
[4,] 2 2 

Quindi, se si dispone di tutti i dati numerici, va bene.

+3

Ma ti troverai nei guai se hai diversi tipi di dati nel df. – Roland

+0

@Roland Yup, ho appena modificato in tal senso. Comunque intorno a questo? – Thomas

+1

Sì, scrivi una funzione 'rbindByIndex', che l'OP esplicitamente non vuole fare ... – Roland

Problemi correlati