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?
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.
library(data.table)
library(mltools)
customers_1h <- one_hot(as.data.table(customers))
> 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
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))
Voici une solution simple pour coder à chaud votre catégorie sans utiliser de paquet.
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.
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.
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)
}