2016-06-19 22 views
5

Mi imbatto in elenchi che vorrei analizzare prima di eseguire il coercing in un frame di dati. A volte ho liste che contengono elementi che non mi aspetto. Mi piacerebbe essere in grado di rimuovere tutti questi elementi inaspettati per nome quando si presentano. Ecco un esempio di un elenco con un elemento wackything che vorrei rimosso senza dover chiamare l'indice elemento o utilizzando un ciclo for attraverso ogni elemento secondario.rimuovere un elemento se esiste per tutti i sottoelementi di un elenco

my_list <- list(person = list(name = "mike", phone = "111-1111"), 
person = list(name = "lisa", phone = "222-2222", wackything = "PLEASE REMOVE ME"), 
person = list(name = "kimo", phone = "333-3333")) 

vorrei che la mia lista finale di simile a questa:

final_list <- list(person = list(name = "mike", phone = "111-1111"), 
      person = list(name = "lisa", phone = "222-2222"), 
      person = list(name = "kimo", phone = "333-3333")) 

modo che io possa corece ad un frame di dati utilizzando

do.call(rbind, lapply(final_list, rbind)) 

risposta

6

Penso che tu abbia troppi rbinds nel tuo uso previsto. Vedere se questo è soddisfacente:

> rmwac <- function(x) x[ !names(x) %in% "wackything"] 
> do.call(rbind, lapply(my_list, rmwac)) 
     name phone  
person "mike" "111-1111" 
person "lisa" "222-2222" 
person "kimo" "333-3333" 

noti che epi10 è perfettamente risposta fini usare un segno negativo e che è stato possibile perché grep restituisce valori numerici e l'indicizzazione di liste con i valori numerici è possibile. Tuttavia, non è possibile utilizzare il segno negativo con caratteri e valori logici.

+0

Grazie! A R non piacciono i nomi di riga duplicati quando lo converte in un data.frame. – cylondude

+0

Usa: 'as.data.frame (do.call (rbind, lapply (mia_elenco, rmwac)), row.names = -1)' –

4

bind_rows dal pacchetto dplyr funzionerà anche se non tutti gli elenchi condividono gli stessi nomi di elementi. Quindi puoi rimuovere le colonne che non ti servono.

library(dplyr) 

df = bind_rows(my_list) 
name phone  wackything 
1 mike 111-1111    NA 
2 lisa 222-2222 PLEASE REMOVE ME 
3 kimo 333-3333    NA 
df = df[ , -grep("wackything", names(df))] 
name phone 
1 mike 111-1111 
2 lisa 222-2222 
3 kimo 333-3333 
2

Si potrebbe provare questo. Il primo passo è simile alla risposta di 42. Quindi usiamo sapply, che restituisce una matrice che dobbiamo quindi trasporre.

my_list <- lapply(my_list, function(x)x[names(x)!= "wackything"]) 
data.frame(t(sapply(my_list,c)), row.names=NULL) 

# name phone 
#1 mike 111-1111 
#2 lisa 222-2222 
#3 kimo 333-3333 

Un'altra opzione che offre lo stesso risultato.

data.frame(Reduce(rbind, my_list), row.names=NULL) 

Utilizziamo row.names=NULL durante la creazione del dataframe. Puoi farlo senza ma questo si tradurrà in un messaggio di avviso relativo ai giochi di ruolo duplicati che abbiamo.