Создать новые столбцы фиктивной переменной из категориальной переменной - PullRequest
39 голосов
/ 02 августа 2010

У меня есть несколько наборов данных с 75 000 наблюдений и переменной type, которая может принимать значение 0-4.Я хочу добавить пять новых фиктивных переменных в каждый набор данных для всех типов.Лучший способ, которым я мог бы придумать, это сделать следующим образом:

# For the 'binom' data set create dummy variables for all types in all data sets
binom.dummy.list<-list()
for(i in 0:4){
    binom.dummy.list[[i+1]]<-sapply(binom$type,function(t) ifelse(t==i,1,0))
}

# Add and merge data
binom.dummy.df<-as.data.frame(do.call("cbind",binom.dummy.list))
binom.dummy.df<-transform(binom.dummy.df,id=1:nrow(binom))
binom<-merge(binom,binom.dummy.df,by="id")

Хотя это работает, это невероятно медленно (функция слияния даже несколько раз терпела крах).Есть ли более эффективный способ сделать это?Возможно, эта функциональность является частью пакета, с которым я не знаком?

Ответы [ 7 ]

49 голосов
/ 02 августа 2010

R имеет «дополнительный язык» для перевода формул в матрицу дизайна, и в духе языка вы можете воспользоваться этим. Это быстро и лаконично. Пример: у вас есть кардинальный предиктор x, категориальный предиктор catVar и ответ y.

> binom <- data.frame(y=runif(1e5), x=runif(1e5), catVar=as.factor(sample(0:4,1e5,TRUE)))
> head(binom)
          y          x catVar
1 0.5051653 0.34888390      2
2 0.4868774 0.85005067      2
3 0.3324482 0.58467798      2
4 0.2966733 0.05510749      3
5 0.5695851 0.96237936      1
6 0.8358417 0.06367418      2

Вы просто делаете

> A <- model.matrix(y ~ x + catVar,binom) 
> head(A)
  (Intercept)          x catVar1 catVar2 catVar3 catVar4
1           1 0.34888390       0       1       0       0
2           1 0.85005067       0       1       0       0
3           1 0.58467798       0       1       0       0
4           1 0.05510749       0       0       1       0
5           1 0.96237936       1       0       0       0
6           1 0.06367418       0       1       0       0

Готово.

24 голосов
/ 02 августа 2010

Дрю, это намного быстрее и не должно вызывать сбоев.

> binom <- data.frame(data=runif(1e5),type=sample(0:4,1e5,TRUE))
> for(t in unique(binom$type)) {
+   binom[paste("type",t,sep="")] <- ifelse(binom$type==t,1,0)
+ }
> head(binom)
        data type type2 type4 type1 type3 type0
1 0.11787309    2     1     0     0     0     0
2 0.11884046    4     0     1     0     0     0
3 0.92234950    4     0     1     0     0     0
4 0.44759259    1     0     0     1     0     0
5 0.01669651    2     1     0     0     0     0
6 0.33966184    3     0     0     0     1     0
16 голосов
/ 02 августа 2010

А как насчет использования model.matrix ()?

> binom <- data.frame(data=runif(1e5),type=sample(0:4,1e5,TRUE))
> head(binom)
       data type
1 0.1412164    2
2 0.8764588    2
3 0.5559061    4
4 0.3890109    3
5 0.8725753    3
6 0.8358100    1
> inds <- model.matrix(~ factor(binom$type) - 1)
> head(inds)
  factor(binom$type)0 factor(binom$type)1 factor(binom$type)2 factor(binom$type)3 factor(binom$type)4
1                   0                   0                   1                   0                   0
2                   0                   0                   1                   0                   0
3                   0                   0                   0                   0                   1
4                   0                   0                   0                   1                   0
5                   0                   0                   0                   1                   0
6                   0                   1                   0                   0                   0
2 голосов
/ 16 октября 2017

Если вы открыты для использования пакета data.table , mltools имеет метод one_hot ().

library(data.table)
library(mltools)

binom <- data.table(y=runif(1e5), x=runif(1e5), catVar=as.factor(sample(0:4,1e5,TRUE)))
one_hot(binom)

                 y          x catVar_0 catVar_1 catVar_2 catVar_3 catVar_4
     1: 0.90511891 0.83045050        0        0        1        0        0
     2: 0.91375984 0.73273830        0        0        0        1        0
     3: 0.01926608 0.10301409        0        0        1        0        0
     4: 0.48691138 0.24428157        0        1        0        0        0
     5: 0.60660396 0.09132816        0        0        1        0        0
    ---                                                                   
 99996: 0.12908356 0.26157731        0        1        0        0        0
 99997: 0.96397273 0.98959000        0        1        0        0        0
 99998: 0.16818414 0.37460941        1        0        0        0        0
 99999: 0.72610508 0.72055867        1        0        0        0        0
100000: 0.89710998 0.24155507        0        0        0        0        1
1 голос
/ 12 декабря 2017

Пакет рецептов также может быть достаточно мощным, чтобы сделать это. Пример ниже довольно подробный, но он может быть действительно чистым, как только вы добавите больше шагов предварительной обработки.

library(recipes)

binom <- data.frame(y = runif(1e5), 
                    x = runif(1e5),
                    catVar = as.factor(sample(0:4, 1e5, TRUE))) # use the example from gappy
head(binom)

new_data <- recipe(y ~ ., data = binom) %>% 
  step_dummy(catVar) %>% # add dummy variable
  prep(training = binom) %>% # apply the preprocessing steps (could be more than just adding dummy variables)
  bake(newdata = binom) # apply the recipe to new data
head(new_data)

Другими примерами шагов являются step_scale, step_center, step_pca и т. Д.

0 голосов
/ 04 апреля 2018

Пакет nnet для однослойных нейронных сетей (которые не понимают факторы) имеет команду преобразования: class.ind.

0 голосов
/ 02 августа 2010

ifelse векторизовано, поэтому, если я правильно понимаю ваш код, вам это не нужно sapply.И я бы не использовал слияние - я бы использовал SQLite или PostgreSQL.

Некоторые примеры данных тоже могут помочь: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...