web-dev-qa-db-fra.com

Comment encoder à chaud plusieurs variables qualitatives dans R

Je travaille sur un problème de prédiction et je construis un arbre de décision en R. J'ai plusieurs variables catégoriques et j'aimerais les coder en une seule fois de manière cohérente dans mon ensemble de formation et de test. J'ai réussi à le faire sur mes données d'entraînement avec:

temps <- X_train
tt <- subset(temps, select = -output)
oh <- data.frame(model.matrix(~ . -1, tt), CLASS = temps$output)

Mais je ne trouve pas le moyen d'appliquer le même encodage sur mon ensemble de test. Comment puis-je faire cela?

9
xeco

Je recommande d'utiliser la fonction dummyVars dans le package caret:

customers <- data.frame(
  id=c(10, 20, 30, 40, 50),
  gender=c('male', 'female', 'female', 'male', 'female'),
  mood=c('happy', 'sad', 'happy', 'sad','happy'),
  outcome=c(1, 1, 0, 0, 0))
customers
id gender  mood outcome
1 10   male happy       1
2 20 female   sad       1
3 30 female happy       0
4 40   male   sad       0
5 50 female happy       0


# dummify the data
dmy <- dummyVars(" ~ .", data = customers)
trsf <- data.frame(predict(dmy, newdata = customers))
trsf
id gender.female gender.male mood.happy mood.sad outcome
1 10             0           1          1        0       1
2 20             1           0          0        1       1
3 30             1           0          1        0       0
4 40             0           1          0        1       0
5 50             1           0          1        0       0

exemple source

Vous appliquez la même procédure aux ensembles d'apprentissage et de validation.

23
Esteban PS

Code

library(data.table)
library(mltools)
customers_1h <- one_hot(as.data.table(customers))

Résultat

> customers_1h
id gender_female gender_male mood_happy mood_sad outcome
1: 10             0           1          1        0       1
2: 20             1           0          0        1       1
3: 30             1           0          1        0       0
4: 40             0           1          0        1       0
5: 50             1           0          1        0       0

Les données

customers <- data.frame(
  id=c(10, 20, 30, 40, 50),
  gender=c('male', 'female', 'female', 'male', 'female'),
  mood=c('happy', 'sad', 'happy', 'sad','happy'),
  outcome=c(1, 1, 0, 0, 0))
11
Roman

Voici une solution simple pour coder à chaud votre catégorie sans utiliser de paquet.

Solution

model.matrix(~0+category)

Il faut que votre variable catégorique soit un facteur. Les niveaux de facteur doivent être identiques dans vos données d'entraînement et de test. Vérifiez avec levels(train$category) et levels(test$category). Peu importe si certains niveaux ne figurent pas dans votre ensemble de test.

Exemple

Voici un exemple utilisant le jeu de données iris.

data(iris)
#Split into train and test sets.
train <- sample(1:nrow(iris),100)
test <- -1*train

iris[test,]

    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
34           5.5         4.2          1.4         0.2    setosa
106          7.6         3.0          6.6         2.1 virginica
112          6.4         2.7          5.3         1.9 virginica
127          6.2         2.8          4.8         1.8 virginica
132          7.9         3.8          6.4         2.0 virginica

model.matrix() crée une colonne pour chaque niveau du facteur, même s'il n'est pas présent dans les données. Zéro indique que ce n'est pas ce niveau, on indique qu'il l'est. L'ajout du zéro indique que vous ne voulez pas d'interception ou de niveau de référence et équivaut à -1.

oh_train <- model.matrix(~0+iris[train,'Species'])
oh_test <- model.matrix(~0+iris[test,'Species'])

#Renaming the columns to be more concise.
attr(oh_test, "dimnames")[[2]] <- levels(iris$Species)


  setosa versicolor virginica
1      1          0         0
2      0          0         1
3      0          0         1
4      0          0         1
5      0          0         1

P.S. Il est généralement préférable d’inclure toutes les catégories dans les données d’entraînement et de test. Mais ça ne me regarde pas.

3
D A Wells

Salut voici ma version de la même chose, cette fonction code toutes les variables qualitatives qui sont 'facteurs', et supprime l’une des variables factices à éviter piège des variables nominales et renvoie un nouvelle trame de données avec l'encodage: -

onehotencoder <- function(df_orig) {
  df<-cbind(df_orig)
  df_clmtyp<-data.frame(clmtyp=sapply(df,class))
  df_col_typ<-data.frame(clmnm=colnames(df),clmtyp=df_clmtyp$clmtyp)
  for (rownm in 1:nrow(df_col_typ)) {
    if (df_col_typ[rownm,"clmtyp"]=="factor") {
      clmn_obj<-df[toString(df_col_typ[rownm,"clmnm"])] 
      dummy_matx<-data.frame(model.matrix( ~.-1, data = clmn_obj))
      dummy_matx<-dummy_matx[,c(1,3:ncol(dummy_matx))]
      df[toString(df_col_typ[rownm,"clmnm"])]<-NULL
      df<-cbind(df,dummy_matx)
      df[toString(df_col_typ[rownm,"clmnm"])]<-NULL
    }  }
  return(df)
}
1
Shubham Joshi