创建一个非正统的虚拟变量

时间:2016-05-25 19:55:37

标签: r dataframe dummy-variable

我需要创建一些非正统的虚拟变量,我遇到了一些麻烦。基本上在我的数据集中,每个教师都可以教授多个课程。我正在构建一个多级数据集,因此可以存在重复的教师ID。

以下是数据示例:

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

正如您所看到的,ID为1和3的教师都会教授2个不同的班级。

创建虚拟变量的传统方法产生:

# 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

但是,我希望看到新的虚拟变量:

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

我的预感是我需要循环通过ID来创建这些,但过去我真的没有看到我的途径来完成我想要的东西。

4 个答案:

答案 0 :(得分:4)

这是一个基本的R方法。我们的想法是为每位教师创建假人,然后将这些假人合并到原始数据中:

# 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")

如果它真的给你带来了麻烦,你可以将逻辑强制转换为整数,但R会为你做所有有用的工作。

答案 1 :(得分:3)

您也可以使用%in%

执行此操作
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')

这会给你TRUE / FALSE而不是0/1向量,但as.integer会在必要时将它们转换为0/1。

答案 2 :(得分:2)

只是为了好玩,使用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))
  )

输出:

   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

答案 3 :(得分:1)

我使用dplyrtidyr

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

然后,您可以使用连接将它们包含在原始数据中。

> 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