40 votes

Créer de nouvelles colonnes de variables factices à partir d'une variable catégorielle

J'ai plusieurs jeux de données avec 75 000 observations et une type variable qui peut prendre une valeur de 0 à 4. Je veux ajouter cinq nouvelles variables muettes pour chaque jeu de données pour tous les types. Le mieux que j'ai pu trouver pour faire ceci est comme suit:

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

Bien que cela fonctionne, il est incroyablement lent (la fonction de fusion a même écrasé à quelques reprises). Est-il un moyen plus efficace de faire cela? Peut-être cette fonctionnalité fait partie d'un paquet que je ne suis pas familier avec?

Merci pour toute aide!

49voto

gappy Points 3573

R a un "sous-langage" pour traduire les formules en matrice de conception, et dans l'esprit du langage, vous pouvez en profiter. C'est rapide et concis. Exemple: vous avez un prédicteur cardinal x, un prédicteur catégoriel catVar et une réponse 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
 

Tu fais juste

 > 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
 

Terminé.

24voto

Joshua Ulrich Points 68776

Drew, c'est beaucoup plus rapide et ne devrait pas provoquer de crash.

 > 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
 

16voto

griverorz Points 251

Qu'en est-il de l'utilisation de 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
 

0voto

Vince Points 3980

ifelse est vectorisé, donc si je comprends bien votre code, vous n'avez pas besoin de ce sapply . Et je n'utiliserais pas la fusion - j'utiliserais SQLite ou PostgreSQL.

Quelques exemples de données pourraient aussi aider :-)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X