2016-06-18 10 views
1

Meine Frage enthält, ist wie folgt:Datentabelle - wie eine neue Variable durch eine Spalte indiziert zu erzeugen, die die Spaltennamen von Interesse

Ich mag würde Spalte erzeugen d auf der Grundlage der Informationen aus der Spalte c. Die Spalte c enthält die Namen der Spalten, aus denen Daten für die angegebene Zeile abgerufen werden sollen.

a b c d 
1 5 3 a 5 
2 8 6 b 6 
3 12 8 a 12 

Meine aktuelle Methode ist sehr ineffizient:

DT[, d:=mget(c)] 
for(i in 1:nrow(DT)) { e[i] <- DT[,d][[i]][i]} 
DT[,e:=e] 

es sehr schätzen, wenn es irgendeine Einzeiler Lösung.

+0

Die Methode ist eigentlich geschrieben nicht funktioniert ... Bitte senden Sie sich ein klareres Beispiel dafür, was Ihre Frage/gewünschten Ausgang ist –

Antwort

0

Sie können eine ifelse Anweisung:

dt[, d := ifelse(c == "a", a, b)] 
dt 
#  a b c d 
# 1: 5 3 a 5 
# 2: 8 6 b 6 
# 3: 12 8 a 12 

Eine weitere Möglichkeit, Ihre Daten zu prüfen ist, neu zu gestalten, die mit mehreren Spalten Problem umgehen können:

dt[, id := seq_len(nrow(dt))] # create an id column for reshape purpose 
    [melt(dt, id.vars = c("id", "c"))[c == variable], d:=value , on = "id"] 
    # reshape data, select values that match the column names and then join back with the original data. 
    [, id := NULL]     # drop the id column 

dt 
#  a b c d 
# 1: 5 3 a 5 
# 2: 8 6 b 6 
# 3: 12 8 a 12 
+0

Danke, Psidom. Allerdings habe ich etwa 150 Spalten und das Beispiel ist eine vereinfachte Version des ursprünglichen Problems ... –

+0

@LukeShi Sie sollten die Dimensionen des zugrunde liegenden Problems in Ihrer Frage angegeben haben. Einige der Antworten wurden durch den Mangel an Details in die Irre geführt. Denken Sie auch daran, den Code zum Erstellen Ihrer Beispieldaten mit Ihrer Frage anzugeben, um die Zeit der antwortenden Personen zu sparen. Vielen Dank. – Uwe

2

Sie selbst eigentlich nicht brauchen data.table Wenn Sie nicht möchten:

DT$d <- sapply(1:nrow(DT),function(i){DT[i,get(as.character(DT[i,c]))]}) 

> DT 
    a b c d 
1: 5 3 a 5 
2: 8 6 b 6 
3: 12 8 a 12 

Diese Lösung Außerdem ist es flexibler, c kann auf jede Spalte in den Daten verweisen.

Daten

DT<-structure(list(a = c(5L, 8L, 12L), b = c(3L, 6L, 8L), c = structure(c(1L, 
2L, 1L), .Label = c("a", "b"), class = "factor")), .Names = c("a", 
"b", "c"), class = c("data.table", "data.frame"), row.names = c(NA, 
-3L), .internal.selfref = <pointer: 0x00000000001f0788>) 
+0

Danke Mike. Allerdings hatte ich ein kleines Problem mit dem Code, von dem ich nach unten modifiziert, was funktionierte. sapply (1: nrow (DT), Funktion (i) {DT [i, get (eval (DT [i, c]))]}) –

+0

Hmm, es sollte unabhängig davon funktionieren, ob Sie 'c' oder nicht ist ein Charakter oder Faktor. Wohingegen ich denke, dass dein Code nur funktioniert, wenn 'DT $ c' ein Zeichen ist. Können Sie den Fehler posten? –

+0

Ich bekomme diesen Fehler: Fehler in DT [1, c]: falsche Anzahl der Dimensionen. Ich habe Eval verwendet, um den Fehler verschwinden zu lassen ... –

1

Ihre Daten:

a <- c(5,8,12) 
b <- c(3,6,8) 
c <- c("a", "b", "a") 
df <- as.data.frame(cbind(a,b,c)) 

Dies ist, wie Sie es tun könnte.

d <- NULL 
for (i in 1:NROW(df)){d <- c(d, as.character(df[i,as.character(c[i])]))} 
df$d <- d 

# a b c d 
#1 5 3 a 5 
#2 8 6 b 6 
#3 12 8 a 12 

Auf diese Weise können Sie das gleiche wie oben in der for-Schleife nur 1 Zeile Code mit tun (ähnlich MikeyMike Antwort).

df$d <- sapply(1:NROW(df), function(i){as.character(df[i,as.character(c[i])])}) 
+0

Danke Milan für die data.frame-Lösung, das funktioniert. Da ich mit einer sehr großen data.table arbeite, frage ich mich, ob datenspezifische Methoden die Geschwindigkeit verbessern könnten. –

6

Sie können Gruppe durch die Werte in Spalte c, und verwenden Sie get() die Werte zu erhalten.

dt[, d := get(c), by = c] 

die

dt 
#  a b c d 
# 1: 5 3 a 5 
# 2: 8 6 b 6 
# 3: 12 8 a 12 

Daten gibt:

dt <- data.table(a = c(5, 8, 12), b = c(3, 6, 8), c = c("a", "b", "a")) 
+0

Ich habe das versucht aber bekam: Fehler in '[.data.frame' (dt,,': = '(d, get (c)), durch = seq_len (nrow (dt))): unbenutztes Argument (durch = seq_len (nrow (dt))) – milan

+0

@milan - Haben Sie 'library (data.table)'? Dies ist eine data.table getaggte Frage, also dachte ich nicht, dass es notwendig war. –

+0

Großartig, danke. Eine Sache noch. Wenn ich das ':' reinlasse, funktioniert es nicht. Gibt eine Fehlermeldung aus. Ohne es funktioniert gut? – milan