Ich arbeite an einem Vorhersageproblem und erstelle in R einen Entscheidungsbaum. Ich habe mehrere kategoriale Variablen und möchte sie in meinem Trainings- und Testset konsistent per One-Hot-Codierung codieren. Ich habe es mit meinen Trainingsdaten geschafft:
temps <- X_train
tt <- subset(temps, select = -output)
oh <- data.frame(model.matrix(~ . -1, tt), CLASS = temps$output)
Ich kann jedoch nicht die gleiche Codierung auf meinem Testset anwenden. Wie kann ich das tun?
Ich empfehle die Verwendung der dummyVars-Funktion im Caret-Paket:
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
beispiel Quelle
Sie wenden das gleiche Verfahren auf die Trainings- und Validierungssätze an.
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))
Hier ist eine einfache Lösung, um Ihre Kategorie mit nur einem Tastendruck ohne Pakete zu kodieren.
model.matrix(~0+category)
Ihre kategoriale Variable muss ein Faktor sein. Die Faktorstufen müssen in Ihren Trainings- und Testdaten gleich sein, prüfen Sie mit levels(train$category)
und levels(test$category)
. Es spielt keine Rolle, ob einige Level in Ihrem Test-Set nicht vorkommen.
Hier ist ein Beispiel mit dem Iris-Datensatz.
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()
erstellt eine Spalte für jede Ebene des Faktors, auch wenn sie nicht in den Daten vorhanden ist. Null zeigt an, dass es nicht dieses Niveau ist, man zeigt an, dass es ist. Das Hinzufügen der Null gibt an, dass Sie keinen Schnittpunkt oder Referenzpegel möchten, und entspricht -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. Im Allgemeinen ist es vorzuziehen, alle Kategorien in die Trainings- und Testdaten aufzunehmen. Aber das geht mich nichts an.
Hallo, hier ist meine Version derselben, diese Funktion codiert alle kategorialen Variablen, die 'Faktoren' sind, und entfernt eine der Dummy-Variablen, um Dummy-Variablen-Trap zu vermeiden, und gibt ein zurück neuer Datenrahmen mit der Kodierung: -
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)
}