2014-10-10 10 views
5

Vorrei modificare un set di colonne in un data.table per essere fattori. Se conoscessi i nomi delle colonne in anticipo, penso che sarebbe semplice.Posso aggiornare a livello di codice il tipo di un insieme di colonne (in fattori) in data.table?

library(data.table) 
dt1 <- data.table(a = (1:4), b = rep(c('a','b')), c = rep(c(0,1))) 
dt1[,class(b)] 
dt1[,b:=factor(b)] 
dt1[,class(b)] 

Ma non fare, e invece hanno un elenco dei nomi delle variabili

vars.factors <- c('b','c') 

posso applicare la funzione di fattore di loro senza un problema ...

lapply(vars.factors, function(x) dt1[,class(get(x))]) 
lapply(vars.factors, function(x) dt1[,factor(get(x))]) 
lapply(vars.factors, function(x) dt1[,factor(get(x))]) 

Ma non so come riassegnare o aggiornare la colonna originale nella tabella dei dati.

Questo fallisce ...

lapply(vars.factors, function(x) dt1[,x:=factor(get(x))]) 
    # Error in get(x) : invalid first argument 

Come fa questo ...

lapply(vars.factors, function(x) dt1[,get(x):=factor(get(x))]) 
    # Error in get(x) : object 'b' not found 

NB. Ho provato la risposta proposta here senza fortuna.

+0

ricerca di questo? dt2 = as.data.table (lapply (dt1, factor)) – KFB

risposta

12

Sì, questo è abbastanza semplice:

dt1[, (vars.factors) := lapply(.SD, as.factor), .SDcols=vars.factors] 

Nel LHS (di: = in j), specifichiamo i nomi delle colonne. Se una colonna esiste già, verrà aggiornata, altrimenti verrà creata una nuova colonna. Nel RHS, eseguiamo il loop su tutte le colonne in .SD (che corrisponde a S ubset di D ata) e specifichiamo le colonne che dovrebbero essere in .SD con l'argomento .SDcols.

In seguito al commento:

Nota che abbiamo bisogno di avvolgere LHS con () per essere valutato e recuperare i nomi delle colonne all'interno vars.factors variabile. Questo perché permettiamo la sintassi

DT[, col := value] 

quando c'è solo una colonna per assegnare, specificando il nome della colonna come un simbolo (senza virgolette), solo per convenienza. Ciò crea una colonna denominata col e assegna value a esso.

Per distinguere questi due casi, abbiamo bisogno dello (). Avvolgendolo con () è sufficiente identificare che abbiamo davvero bisogno di ottenere i valori all'interno della variabile.

+0

Grazie - funziona. Avevo provato questo 'dt1 [, vars.factors: = lapply (.SD, function (x) factor (x)), .SDcols = vars.factors]' prima, ma sembra che faccia qualcosa di molto diverso. Qualche possibilità che potresti spiegare perché? – drstevok

+1

Grazie per la spiegazione aggiuntiva – drstevok

2

Utilizzando frame di dati:

> df1 = data.frame(dt1) 
> df1[,vars.factors] = data.frame(sapply(df1[,vars.factors], factor)) 
> dt1 = data.table(df1) 

> dt1 
    a b c 
1: 1 1 b 
2: 2 2 c 
3: 3 3 b 
4: 4 4 c 

> str(dt1) 
Classes ‘data.table’ and 'data.frame': 4 obs. of 3 variables: 
$ a: int 1 2 3 4 
$ b: Factor w/ 4 levels "1","2","3","4": 1 2 3 4 
$ c: Factor w/ 2 levels "b","c": 1 2 1 2 
- attr(*, ".internal.selfref")=<externalptr> 
+0

L'idea è buona, ma questo non è il modo per farlo. Non c'è bisogno in 'data.frame' due volte qui. Si potrebbe fare tutto in una riga, come 'dt1 [vars.factors] <- lapply (setDF (dt1) [vars.fattori], fattore); setDT (dt1) ' –

+0

@ DavidArenburg: la tua soluzione è elegante. Ho usato funzioni minime per ottenere la soluzione. – rnso

Problemi correlati