每年的虚拟变量

时间:2014-11-26 05:18:53

标签: r

如果我有以下data.frame,我将如何为每年创建一个虚拟变量并将其附加到DF,这样就会有额外的列year2010和year2011。我有一个相当大的数据集,有很多不同的年份,我不想使用ifelse 50次。 ddply?

由于

 DF <- read.table(text=" year     id     var     ans
     2010      1      1       1
     2010      2      0       0
     2010      1      0       1
     2010      1      0       1
     2011      2      1       1
     2011      2      0       1
     2011      1      0       0
     2011      1      0       0", header=TRUE)

期望的输出:

  year id var ans year_2010 year_2011
1 2010  1   1   1         1         0
2 2010  2   0   0         1         0
3 2010  1   0   1         1         0
4 2010  1   0   1         1         0
5 2011  2   1   1         0         1
6 2011  2   0   1         0         1
7 2011  1   0   0         0         1
8 2011  1   0   0         0         1

1

5 个答案:

答案 0 :(得分:4)

这是我最喜欢的用于从分类变量创建虚拟变量的代码。 唯一的区别是这段代码产生K-1虚拟变量以避免共线:

x = as.factor( rep(1:6,each=4) );
model.matrix(~x)[,-1]

用您的数据集中的年份替换x

答案 1 :(得分:4)

只需使用table,就像这样:

cbind(DF, as.data.frame.matrix(table(sequence(nrow(DF)), DF$year)))
  year id var ans 2010 2011
1 2010  1   1   1    1    0
2 2010  2   0   0    1    0
3 2010  1   0   1    1    0
4 2010  1   0   1    1    0
5 2011  2   1   1    0    1
6 2011  2   0   1    0    1
7 2011  1   0   0    0    1
8 2011  1   0   0    0    1

您还应该能够做到这样的事情:

library(data.table)
cbind(DF, 
      dcast.data.table(as.data.table(DF, keep.rownames = TRUE), 
                       rn ~ year, value.var = "id", fun.aggregate = length))
#   year id var ans rn 2010 2011
# 1 2010  1   1   1  1    1    0
# 2 2010  2   0   0  2    1    0
# 3 2010  1   0   1  3    1    0
# 4 2010  1   0   1  4    1    0
# 5 2011  2   1   1  5    0    1
# 6 2011  2   0   1  6    0    1
# 7 2011  1   0   0  7    0    1
# 8 2011  1   0   0  8    0    1

如果您希望姓名为&#34; year_2010&#34;等等,我想解决方法是做这样的事情:

dcast.data.table(as.data.table(DF, keep.rownames = TRUE)[, yr := "year"], 
                 rn ~ yr + year, value.var = "id", fun.aggregate = length)

您也可以随时编写自己的功能。在这里我鞭打了一个应该合理有效的人:

dummyCreator <- function(invec, prefix = NULL) {
  L <- length(invec)
  ColNames <- sort(unique(invec))
  M <- matrix(0L, ncol = length(ColNames), nrow = L,
              dimnames = list(NULL, ColNames))
  M[cbind(seq_len(L), match(invec, ColNames))] <- 1L
  if (!is.null(prefix)) colnames(M) <- paste(prefix, colnames(M), sep = "_")
  M
} 

dummyCreator(DF$year, prefix = "year")
#      year_2010 year_2011
# [1,]         1         0
# [2,]         1         0
# [3,]         1         0
# [4,]         1         0
# [5,]         0         1
# [6,]         0         1
# [7,]         0         1
# [8,]         0         1

只需使用上述cbind即可获得您期望的输出。

答案 2 :(得分:2)

也许这个?

library(tidyr)
DF$row <- 1:nrow(DF)  # to make each row unique
DF$dummy <- 1

newdf <- spread(DF, year, dummy, fill = 0)

答案 3 :(得分:2)

 for(i in unique(DF$year)) {
          DF[paste('year',i,sep="")]=DF$year==i
  }

答案 4 :(得分:2)

正如Andrey Shabalin所说,你想要model.matrix。首先,您需要将year列转换为一个因素。要准确获得所需内容,您需要在caret包中使用contr.ltfr contr.treatment的修改版本。

在下面的公式中,0表示不使用截距,.表示数据框中的所有列。

DF$year <- factor(DF$year)
model.matrix(
  ~ 0 + ., 
  DF, 
  contrasts.arg = list(year = "contr.ltfr")
)