2014-11-26 2 views
1

Если у меня есть следующий файл data.frame, как бы я начал создавать фиктивную переменную за каждый год и прикрепить ее к DF, тогда появятся дополнительные столбцы year2010 и year2011. У меня довольно большой набор данных с разными годами, и я не хочу использовать ifelse 50 раз. ddply?Dummy Variable для каждого года

Благодаря

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 
+0

В DF у вас уже есть «год». Это то, чего вы ожидаете? Или это часть ДФ? – jazzurro

+0

@jazzurro Мне нужны фиктивные переменные столбцы, дифференцирующие годы. – Vedda

+0

Пожалуйста, покажите желаемый результат с помощью этого ввода. – A5C1D2H2I1M1N2O1R2T1

ответ

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 

Если вы хотите имена, чтобы быть " year_2010 "и так далее, я думаю, что обходным решением было бы сделать что-то вроде этого:

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, как описано выше, чтобы получить выход вы ожидаете.

+0

Это хорошая идея. Принимая к сведению сейчас. плюс один. :) – jazzurro

+0

Это сработало, но всякий раз, когда я нажимаю на Data in Rstudio, фиктивные переменные не отображаются. Ты знаешь почему? – Vedda

+0

@Amstell, вы назначили выход? – A5C1D2H2I1M1N2O1R2T1

4

Вот мой любимый код для создания фиктивных переменных из категориальной переменной. Единственное отличие состоит в том, что этот код производит K-1 фиктивную переменную, чтобы избежать колинеарности:

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

замещающий x с годом из набора данных.

+0

Это не работает и выдает ошибку с размерами – Vedda

+0

Не забудьте применить 'as.factor' к столбцу года перед запуском кода. –

+0

'model.matrix (~ as.factor (DF $ year)) [, - 1]' –

2

возможно это?

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

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

Это работает, но удаляет столбец года из data.frame – Vedda

+0

@Amstell не проблема: 'newdf $ year = DF $ year'. – Gregor

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

Это работает, но только дает мне true и false – Vedda

+0

@Amstell не проблема: просто оберните в 'as.numeric()'. – Gregor

2

Как уже упоминалось Андрей Шабалин, вы хотите model.matrix. Сначала вам необходимо преобразовать столбец year. Чтобы получить именно то, что вы хотите, вам нужно использовать contr.ltfr, модифицированную версию contr.treatment в пакете caret.

В приведенной ниже формуле 0 означает, что не используется перехват, а . представляет все столбцы в фрейме данных.

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

Спасибо за ваш ответ, но у меня есть 166 переменных в моем текущем наборе данных, и я ищу самый быстрый способ сделать это без ifelse и перечисления всех переменных, которые я хочу сохранить. – Vedda

+1

Вместо того, чтобы вставлять формулу, вы можете просто сделать ее '~. + 0'. – Gregor

+0

@Gregor Спасибо, формула обновлена. –

Смежные вопросы