2014-10-10 14 views
5

Ich möchte eine Reihe von Spalten in einer data.table zu Faktoren ändern. Wenn ich die Namen der Spalten im Voraus wüsste, denke ich, dass das einfach wäre.Kann ich programmgesteuert den Typ einer Reihe von Spalten (zu Faktoren) in data.table aktualisieren?

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)] 

Aber ich nicht, und haben stattdessen eine Liste der Variablennamen

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

ich den Faktor Funktion, um sie ohne Probleme anwenden können ...

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))]) 

Ich weiß jedoch nicht, wie ich die ursprüngliche Spalte in der Datentabelle neu zuweisen oder aktualisieren soll.

Dies scheitert ...

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

Da dies tut ...

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

NB. Ich habe die Antwort here ohne Glück versucht.

+0

für diese gesucht? dt2 = as.data.table (lapply (dt1, factor)) – KFB

Antwort

12

Ja, das ist ziemlich einfach:

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

Im LHS (von: = in j), wir die Namen der Spalten angeben. Wenn eine Spalte bereits existiert, wird sie aktualisiert, andernfalls wird eine neue Spalte erstellt. In der RHS-Schleife durchlaufen wir alle Spalten in .SD (was für S ubset D ata steht), und wir spezifizieren die Spalten, die in .SD mit dem .SDcols Argument sein sollten.

Im Anschluss an Kommentar up:

Bitte beachte, dass wir mit () LHS wickeln müssen für sie innerhalb vars.factors Variable ausgewertet und holen die Spaltennamen zu sein. Dies liegt daran, dass wir der Syntax

DT[, col := value] 

erlauben, wenn es nur eine Spalte zuweisen, durch den Spaltennamen als Symbol Angabe (ohne Anführungszeichen), rein für die Bequemlichkeit. Dies erstellt eine Spalte mit dem Namen col und weist ihm value zu.

Um diese beiden Fälle zu unterscheiden, benötigen wir die (). Wenn Sie es mit () einpacken, ist das ausreichend, um zu erkennen, dass wir wirklich die Werte innerhalb der Variablen erhalten müssen.

+0

Danke - das funktioniert. Ich habe dieses 'dt1 [, vars.factors: = lapply (.SD, Funktion (x) Faktor (x)), .SDcols = vars.factors]' vorher versucht, aber es scheint, etwas sehr verschiedenes zu tun. Jede Chance, die du erklären könntest, warum? – drstevok

+1

Vielen Dank für die zusätzliche Erklärung – drstevok

2

Mit Datenrahmen:

> 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

Die Idee ist nett, aber das ist nicht der Weg, dies zu tun. Es gibt keine Notwendigkeit in "data.frame" zweimal hier. Sie könnten die ganze Sache in einer Zeile machen, zB 'dt1 [vars.factors] <- lapply (setDF (dt1) [vars.Faktoren], Faktor); setDT (dt1) ' –

+0

@ DavidArenburg: Ihre Lösung ist elegant. Ich habe minimale Funktionen verwendet, um die Lösung zu bekommen. – rnso