Создайте новые фиктивные переменные столбцы из категориальной переменной

У меня есть несколько наборы данных с 75 000 наблюдений и a 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")

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

39
задан Community 14 July 2015 в 00:24
поделиться

4 ответа

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

Готово.

49
ответ дан 27 November 2019 в 02:20
поделиться

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

> 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
24
ответ дан 27 November 2019 в 02:20
поделиться

А как насчет использования 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
16
ответ дан 27 November 2019 в 02:20
поделиться

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

Некоторые примеры данных тоже бы помогли :-)

0
ответ дан 27 November 2019 в 02:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: