如何在R中对多个分类变量进行热编码

如何在R中对多个分类变量进行热编码,r,one-hot-encoding,R,One Hot Encoding,我正在研究一个预测问题,我正在R中建立一个决策树,我有几个分类变量,我想在我的训练和测试集中对它们进行一致的热编码。 我利用我的培训数据成功地做到了这一点: temps <- X_train tt <- subset(temps, select = -output) oh <- data.frame(model.matrix(~ . -1, tt), CLASS = temps$output) temps我建议在插入符号包中使用dummyVars函数: customers &

我正在研究一个预测问题,我正在R中建立一个决策树,我有几个分类变量,我想在我的训练和测试集中对它们进行一致的热编码。 我利用我的培训数据成功地做到了这一点:

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

temps我建议在插入符号包中使用dummyVars函数:

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

customersHi这是我的版本,此函数对属于因子的所有分类变量进行编码,并删除其中一个伪变量以避免伪变量陷阱,并返回带有编码的新数据帧:-

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)
}
onehotcoder代码
资料

客户这里有一个简单的解决方案,可以不使用任何软件包对您的类别进行热编码

解决方案
model.matrix(~0+类别)

它需要你的分类变量成为一个因素。训练和测试数据中的系数级别必须相同,请使用
级别(训练$category)
级别(测试$category)
进行检查。如果测试集中没有出现某些级别,这并不重要

例子 下面是一个使用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
附言。
通常,最好在培训和测试数据中包含所有类别。但这不关我的事。

如果您不想使用任何外部软件包,我有自己的功能:

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)
}

编码是指创建虚拟变量吗?用同样的方法。什么不同?是的,我的意思是创建假人:对于每个分类变量,我需要创建尽可能多的假人,因为变量中有不同的类别。@Gregor不同的是,有些类别可能出现在测试集中,而不是在培训中,而且假人的顺序很重要,这两个类别不一样sets@xeco我建议您在RI中查找vtreat包,发现插入符号方法(使用dummyVars)比
mltools
包中的
one\u hot()
函数快约73%。使用
microbenchmark
包和
iris
数据集,插入符号方法在0.025毫秒内完成,而
one_hot()
方法在0.095毫秒内完成。@DaleKube您是否在基准测试中包含
data.frame(predict(dmy,newdata=customers))
?显然,
dummyVars
本身并不能提供实际的假人如果你有一个包含不同变量的数据帧,并且你想对其中的一些进行热编码,你需要使用类似于
dummyVars的东西(“~VARIABLE1+VARIABLE2”,data=customers)
@raffamaiden是的,我包括了predict()调用并转换为data.frame。这里有一个使用recipes(tidymodels)包的替代方法:这对一个变量很有效,但如果有多个分类变量,则不会影响每个类别。如果是,请参阅
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))
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
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
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"))