提问人:xeco 提问时间:2/7/2018 最后编辑:Esteban PSxeco 更新时间:11/21/2023 访问量:89350
如何在 R 中对多个分类变量进行热编码
How to one hot encode several categorical variables in R
问:
我正在研究一个预测问题,我正在 R 中构建一个决策树,我有几个分类变量,我想在我的训练和测试集中一致地对它们进行一热编码。 我设法在我的训练数据上做到了:
temps <- X_train
tt <- subset(temps, select = -output)
oh <- data.frame(model.matrix(~ . -1, tt), CLASS = temps$output)
但是我找不到在我的测试集上应用相同编码的方法,我该怎么做?
答:
48赞
Esteban PS
2/7/2018
#1
我建议在插入符号包中使用 dummyVars 函数:
library(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
示例源
将相同的过程应用于训练集和验证集。
评论
11赞
Dale Kube
12/19/2018
我发现插入符号方法(使用 dummyVars)比包中的函数快约 73%。使用包和数据集,插入符号方法在 0.025 毫秒内完成,而该方法在 0.095 毫秒内完成。one_hot()
mltools
microbenchmark
iris
one_hot()
1赞
robertspierre
4/22/2019
@DaleKube,您在基准测试中包括了这些内容?显然,仅凭这一点不会给你真正的假人data.frame(predict(dmy, newdata = customers))
dummyVars
3赞
robertspierre
4/22/2019
如果你有一个具有不同变量的数据帧,并且你只想对其中的一些变量进行单热编码,则需要使用类似dummyVars(" ~ VARIABLE1 + VARIABLE2", data = customers)
1赞
Dale Kube
4/23/2019
@raffamaiden是的,我包括了predict()调用和对data.frame的转换。
0赞
Pablo Casas
7/24/2019
这是使用 recipes (tidymodels) 包的替代方案:blog.datascienceheroes.com/...
3赞
Shubham Joshi
9/18/2018
#2
嗨,这是我的相同版本,此函数对所有作为“因子”的分类变量进行编码,并删除其中一个虚拟变量以避免虚拟变量陷阱,并返回一个编码为:-
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赞
schotti
7/19/2023
由于删除了其中一个虚拟变量,因此可能不应将函数称为“OneHotEncoder”。“one hot”表示一个虚拟人始终是“hot”,即 1 或 TRUE。
0赞
qwr
10/10/2023
我假设的“虚拟变量陷阱”是独热编码的完美多重共线性。虚拟变量函数应像 dummyVars 一样自动删除一个变量。
22赞
Roman
10/21/2018
#3
法典
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))
31赞
D A Wells
8/28/2019
#4
这是一个简单的解决方案,可以不使用包对类别进行单热编码。
溶液
model.matrix(~0+category)
它需要您的分类变量是一个因子。训练数据和检验数据中的因子水平必须相同,请检查 和 。如果某些级别没有出现在您的测试集中,也没关系。levels(train$category)
levels(test$category)
例
下面是使用鸢尾花数据集的示例。
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()
为因子的每个水平创建一个列,即使数据中不存在该列。零表示它不是那个级别,一个表示它是。添加零指定不需要截距或引用级别,并且等效于 -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
附言 通常,最好在训练和测试数据中包含所有类别。但这不关我的事。
评论
0赞
Gregor Thomas
3/17/2021
这适用于一个变量,但如果有多个分类变量,则不会命中每个类别。
2赞
Aydin K.
3/30/2021
没错,请参阅 stackoverflow.com/questions/62116652/...
4赞
Angel
3/26/2021
#5
如果您不想使用任何外部包,我有自己的函数:
one_hot_encoding = function(df, columns="season"){
# create a copy of the original data.frame for not modifying the original
df = cbind(df)
# convert the columns to vector in case it is a string
columns = c(columns)
# for each variable perform the One hot encoding
for (column in columns){
unique_values = sort(unique(df[column])[,column])
non_reference_values = unique_values[c(-1)] # the first element is going
# to be the reference by default
for (value in non_reference_values){
# the new dummy column name
new_col_name = paste0(column,'.',value)
# create new dummy column for each value of the non_reference_values
df[new_col_name] <- with(df, ifelse(df[,column] == value, 1, 0))
}
# delete the one hot encoded column
df[column] = NULL
}
return(df)
}
你像这样使用它:
df = one_hot_encoding(df, c("season"))
评论
0赞
pd441
10/13/2022
这是最好的答案!
评论