2016-05-25 15 views
2

Ich muss einige unorthodoxe Dummy-Variablen erstellen und habe Probleme. Im Wesentlichen kann jeder Lehrer in meinem Datensatz mehrere Klassen unterrichten. Ich erstelle ein mehrstufiges Dataset, daher ist es in Ordnung, dass doppelte Lehrer-IDs vorhanden sind. HierErstellen einer unorthodoxen Dummy-Variablen

ist ein Beispiel für die Daten:

#generate data 
teacher.id <- c(1:5, 1:5) 
class.taught <- c("ELA", "Math", "Science", "ELA", "Math", "Science", "Math", "ELA", "ELA", "Math") 

# combine into data frame 
dat <- data.frame(teacher.id, class.taught) 

Wie Sie Lehrer mit IDs 1 und 3 beide lehren 2 verschiedene Klassen zu sehen.

Der herkömmliche Ansatz zur Erstellung von Dummy-Ausbeuten Variablen:

# example of what I have done so far 
dat$teach.ELA <- ifelse(dat$class.taught == "ELA", 1, 0) 
dat$teach.MATH <- ifelse(dat$class.taught == "Math", 1, 0) 
dat$teach.SCIENCE <- ifelse(dat$class.taught == "Science", 1, 0) 
dat 

Allerdings ist hier, wie ich die neuen Dummy-Variablen möchte aussehen:

desired.ELA <- c(1,0,1,1,0,1,0,1,1,0) 
desired.MATH <- c(0,1,0,0,1,0,1,0,0,1) 
desired.SCIENCE <- c(1,0,1,0,0,1,0,1,0,0) 
dat.2 <- data.frame(dat, desired.ELA, desired.MATH, desired.SCIENCE) 
dat.2 

Meine Vermutung ist, dass ich Schleife zu müssen durch die Ids, um diese zu schaffen, aber darüber hinaus sehe ich wirklich nicht meinen Weg, um zu erreichen, was ich begehre.

+1

Nicht 'data.frame (cbind (x, y))' da cbind gibt Ihnen eine Zeichenmatrix – Frank

+0

Gibt es eine Regel auf die "gewünscht." Menge von Variablen? – lmo

+1

Ich vermute, es ist wie 'für (crs in Ebenen (dat $ Klasse)) dat [crs] <- ave (dat $ Klasse, dat $ Lehrer, FUN = Funktion (x) crs% in% x)', aber leider ' Ave' kooperiert nicht. Sie können 'für (col in c (" teach.ELA "," teach.MATH "," teach.SCIENCE ")) dat [col] <- ave (dat [col], dat $ lehrer, FUN = max) 'nach Ihrem" konventionellen "Code, aber es ist eher langwierig. – Frank

Antwort

4

Hier ist eine Basis R-Methode. Die Idee ist, dass Sie die Attrappen für jeden Lehrer schaffen und diese dann auf die ursprünglichen Daten zusammenführen:

# get dummies for each teacher 
temp <- as.data.frame(with(dat, table(teacher.id, class.taught) > 0)) 
temp$teacher.id <- as.integer(row.names(temp)) 

# merge onto dataset 
merge(dat, temp, by="teacher.id") 

Sie könnten die Logicals zu integer zwingen, wenn es Sie wirklich nervte, aber R wird für Sie all die Arbeit tun.

+1

Sorry, ich habe es anfangs falsch gelesen. Dies ist ein guter Weg, wahrscheinlich der beste Weg in der Basis R. – Frank

+2

@Frank Manchmal zahlt sich einiges Stata-Wissen aus ... – lmo

2

Just for fun, mit dplyr:

library(dplyr) 
dat %>% left_join(
    dat %>% 
     group_by(teacher.id) %>% 
     summarize(desired.ELA = ifelse(sum(teach.ELA), 1, 0), 
     desired.MATH = ifelse(sum(teach.MATH), 1, 0), 
     desired.SCIENCE = ifelse(sum(teach.SCIENCE), 1, 0)) 
) 

Ausgang:

teacher.id class.taught teach.ELA teach.MATH teach.SCIENCE desired.ELA desired.MATH desired.SCIENCE 
1   1   ELA   1   0    0   1   0    1 
2   2   Math   0   1    0   0   1    0 
3   3  Science   0   0    1   1   0    1 
4   4   ELA   1   0    0   1   0    0 
5   5   Math   0   1    0   0   1    0 
6   1  Science   0   0    1   1   0    1 
7   2   Math   0   1    0   0   1    0 
8   3   ELA   1   0    0   1   0    1 
9   4   ELA   1   0    0   1   0    0 
10   5   Math   0   1    0   0   1    0 
1

Ich würde dplyr und tidyr verwenden.

library(dplyr) 
library(tidyr) 

dummies <- 
dat %>% 
    group_by(teacher.id, class.taught) %>% 
    summarise(is_taught = as.numeric(n() > 0)) %>% 
    spread(class.taught, is_taught, fill = 0) 

> dummies 
Source: local data frame [5 x 4] 

    teacher.id ELA Math Science 
     (int) (dbl) (dbl) (dbl) 
1   1  1  0  1 
2   2  0  1  0 
3   3  1  0  1 
4   4  1  0  0 
5   5  0  1  0 

Sie können sie dann in den Originaldaten mit einem Join haben.

> inner_join(dat, dummies) 
Joining by: "teacher.id" 
    teacher.id class.taught ELA Math Science 
1   1   ELA 1 0  1 
2   2   Math 0 1  0 
3   3  Science 1 0  1 
4   4   ELA 1 0  0 
5   5   Math 0 1  0 
6   1  Science 1 0  1 
7   2   Math 0 1  0 
8   3   ELA 1 0  1 
9   4   ELA 1 0  0 
10   5   Math 0 1  0 
+0

Ich wusste, dass es einen Weg mit dplyr gab! – bfoste01

3

Sie können auch diese %in% mit tun:

dums <- function(dt, x){ 
    ix <- dt[, 2] %in% x 
    dt[, 1] %in% unique(dt[ix, 1]) 
} 

dums(dat, 'ELA') 
dums(dat, 'Math') 
dums(dat, 'Science') 

Dies gibt Ihnen WAHR/FALSCH anstatt 0/1 Vektoren, aber as.integer wird sie auf 0/1 bei Bedarf konvertieren.