2012-02-27 3 views
5

Ho data.frame che contiene diversi fattori e voglio rinominare i livelli dei fattori per tutti questi fattori. Es .:Come assegnare all'interno della famiglia apply?

mydf <- data.frame(col1 = as.factor(c("A","A",NA,NA)),col2 = as.factor(c("A",NA,NA,"A"))) 
mydf <- as.data.frame(lapply(mydf,addNA)) 

Si noti che l'esempio di vita reale ha molto più di due colonne. Quindi vorrei usare applicare per assegnare altri nomi di livello a tutte queste colonne, proprio come in:

levels(mydf$col1) <- c("1","0") 

Ho provato quanto segue ma non ha funzionato ...

apply(mydf,1,function(x) levels(x) <- c("1","0")) 

io non sono veramente sorpreso che non funzioni ma non ho idee migliori al momento. Dovrei usare with forse?

EDIT: Ho realizzato che ho commesso un errore qui semplificando eccessivamente le cose. Ho usato addNA per tenere conto del fatto che le NA non dovrebbero più essere gestite come NA. Così voglio anche relabel loro. Questo non funziona con suggerimento di Andrie e restituisce il seguente messaggio di errore:

labels = c("1", : invalid labels; length 2 should be 1 or 1 

Si noti che ho aggiornato il mio esempio df.

+0

Non si dice cosa si vuole fare con i livelli di NA. Rinominarli a cosa? – Andrie

+0

dopo aver usato addNA Ho i livelli 1 e . E mi piace avere la categoria NA rinominata a 0 - proprio come se fossero normali livelli di fattore e non erano mai stati NA. –

+0

@Charles: cosa c'è di sbagliato nel tag categoriale? Questa è una domanda seria. È perché è così agnostico del linguaggio? Usare il termine R per categoriale ('factor') non sarebbe stato migliore. Dovrei lasciare fuori l'intero aspetto e perché? –

risposta

8

È possibile modificare i livelli per riferimento utilizzando setattr() dai pacchetti bit o data.table. Questo evita copiare l'intero set di dati, e dal momento che hai detto che avere un sacco di Colonne ...

require(bit)   # Either package 
require(data.table) # 
setattr(mydf[[1]],"levels",c("1","0")) 
setattr(mydf[[2]],"levels",c("1","0")) 

che può essere fatto in un semplice for ciclo che è molto veloce. È responsabilità dell'utente assicurarsi di sostituire il vettore dei livelli con un vettore della stessa lunghezza, altrimenti il ​​fattore potrebbe non essere più valido. E, devi sostituire l'intero vettore di livelli con questo metodo. C'è un modo interno in data.table per sostituire determinati nomi di livello per riferimento, ma probabilmente non è necessario andare così lontano.

+1

Perché non 'attr (mydf [[1]]," levels ") <- c (" 1 "," 0 ")' o 'levels (mydf [[1]]) <- c (" 1 "," 0") '? –

+2

@Joshua 'tracemem (mydf)' per prima cosa, vedere le 4 copie (dell'oggetto _whole_). Tieni premuto 'tracemem' e prova' setattr() ': nessuna copia, nessuna. Quindi date 'mydf' a 1 miliardo di righe e guardate gli altri fallire con' out of memory', quando 'setattr()' funziona bene (e rapidamente). –

+0

Ah, naturalmente, perché stai sottomettendo il data.frame. I miei test su un singolo vettore non hanno creato copie. Grazie per il chiarimento. –