R语言实现将分类变量转换为哑变量(dummy vairable)

生成测试数据

a1 <- c(“f”,”f”,”b”,”b”,”c,”c”)

利用nnet包中的函数class.ind

> class.ind(a1)
b c f
[1,] 0 0 1
[2,] 0 0 1
[3,] 1 0 0
[4,] 1 0 0
[5,] 0 1 0
[6,] 0 1 0

class.ind代码

class.ind <- function(cl) {
  n <- length(cl)
  cl <- as.factor(cl)
  x <- matrix( 0,  n ,  length(levels(cl)) )
  # unclass 返回每个字符在level表中的位置
  # 然后按照列计算在向量中的位置
  x[n*(unclass(cl)-1) + (1:n)] <- 1
  dimnames(x) <- list(names(cl), levels(cl))
  x
}

补充:R语言中哑变量的设置

在构建回归模型时,如果自变量X为连续性变量,回归系数β可以解释为:在其他自变量不变的条件下,X每改变一个单位,所引起的因变量Y的平均变化量;如果自变量X为二分类变量,例如是否饮酒(1=是,0=否),则回归系数β可以解释为:其他自变量不变的条件下,X=1(饮酒者)与X=0(不饮酒者)相比,所引起的因变量Y的平均变化量。

但是,当自变量X为多分类变量时,例如职业、学历、血型、疾病严重程度等等,此时仅用一个回归系数来解释多分类变量之间的变化关系,及其对因变量的影响,就显得太不理想。

此时,我们通常会将原始的多分类变量转化为哑变量,每个哑变量只代表某两个级别或若干个级别间的差异,通过构建回归模型,每一个哑变量都能得出一个估计的回归系数,从而使得回归的结果更易于解释,更具有实际意义。

哑变量(Dummy Variable),又称为虚拟变量、虚设变量或名义变量,从名称上看就知道,它是人为虚设的变量,通常取值为0或1,来反映某个变量的不同属性。对于有n个分类属性的自变量,通常需要选取1个分类作为参照,因此可以产生n-1个哑变量。

什么情况下需要设置哑变量

1. 对于无序多分类变量,引入模型时需要转化为哑变量

举一个例子,如血型,一般分为A、B、O、AB四个类型,为无序多分类变量,通常情况下在录入数据的时候,为了使数据量化,我们常会将其赋值为1、2、3、4。

从数字的角度来看,赋值为1、2、3、4后,它们是具有从小到大一定的顺序关系的,而实际上,四种血型之间并没有这种大小关系存在,它们之间应该是相互平等独立的关系。如果按照1、2、3、4赋值并带入到回归模型中是不合理的,此时我们就需要将其转化为哑变量。

2. 对于有序多分类变量,引入模型时需要酌情考虑

例如疾病的严重程度,一般分为轻、中、重度,可认为是有序多分类变量,通常情况下我们也常会将其赋值为1、2、3(等距)或1、2、4(等比)等形式,通过由小到大的数字关系,来体现疾病严重程度之间一定的等级关系。

但需要注意的是,一旦赋值为上述等距或等比的数值形式,这在某种程度上是认为疾病的严重程度也呈现类似的等距或等比的关系。而事实上由于疾病在临床上的复杂性,不同的严重程度之间并非是严格的等距或等比关系,因此再赋值为上述形式就显得不太合理,此时可以将其转化为哑变量进行量化。

3. 对于连续性变量,进行变量转化时可以考虑设定为哑变量

对于连续性变量,很多人认为可以直接将其带入到回归模型中即可,但有时我们还需要结合实际的临床意义,对连续性变量作适当的转换。例如年龄,以连续性变量带入模型时,其解释为年龄每增加一岁时对于因变量的影响。但往往年龄增加一岁,其效应是很微弱的,并没有太大的实际意义。

此时,我们可以将年龄这个连续性变量进行离散化,按照10岁一个年龄段进行划分,如0-10、11-20、21-30、31-40等等,将每一组赋值为1、2、3、4,此时构建模型的回归系数就可以解释为年龄每增加10岁时对因变量的影响。

以上赋值方式是基于一个前提,即年龄与因变量之间存在着一定的线性关系。但有时候可能会出现以下情况,例如在年龄段较低和较高的人群中,某种疾病的死亡率较高,而在中青年人群中,死亡率却相对较低,年龄和死亡结局之间呈现一个U字型的关系,此时再将年龄段赋值为1、2、3、4就显得不太合理了。

因此,当我们无法确定自变量和因变量之间的变化关系,将连续性自变量离散化时,可以考虑进行哑变量转换。

还有一种情况,例如将BMI按照临床诊断标准分为体重过低、正常体重、超重、肥胖等几种分类时,由于不同分类之间划分的切点是不等距的,此时赋值为1、2、3就不太符合实际情况,也可以考虑将其转化为哑变量。

在设定哑变量时,应该选择哪一类作为参照呢?

1. 一般情况下,可以选择有特定意义的,或者有一定顺序水平的类别作为参照

例如,婚姻状态分为未婚、已婚、离异、丧偶等情况,可以将“未婚”作为参照;或者如学历,分为小学、中学、大学、研究生等类别,存在着一定的顺序,可以将“小学”作为参照,以便于回归系数更容易解释。

2. 可以选择临床正常水平作为参照

例如,BMI按照临床诊断标准分为体重过低、正常体重、超重、肥胖等类别,此时可以选择“正常体重”作为参照,其他分类都与正常体重进行比较,更具有临床实际意义。

3. 还可以将研究者所关注的重点类别作为参照

例如血型,分为A、B、O、AB四个类型,研究者更关注O型血的人,因此可以将O型作为参照,来分析其他血型与O型相比后对于结局产生影响的差异。

4. R语言中实现

在R语言中对包括分类变量(factor)的数据建模时,一般会将其自动处理为虚拟变量或哑变量(dummy variable)。但有一些特殊的函数,如neuralnet包中的neuralnet函数就不会预处理。如果直接将原始数据扔进去,会出现”requires numeric/complex matrix/vector arguments”需要数值/复数矩阵/矢量参数错误。

这个时候,除了将这些变量删除,我们只能手动将factor variable转换为取值(0,1)的虚拟变量。所用的函数一般有model.matrix(),nnet package中的class.ind()

下面以UCI的german credit data为例说明。

首先,从UCI网站上下载到german.data数据集,并用str函数对其有个简单的认识。

download.file("http://archive.ics.uci.edu/ml/machine-learning-databases/statlog/german/german.data", "./german.data")
data <- read.table("./german.data")
str(data)

该数据有21个变量,其中V21为目标变量,V1-V20中包括integer和factor两种类型。下面将用V1分类变量(包含4个level)和V2,V5,V8三个数值型变量作为解释变量建模。

## 'data.frame':    1000 obs. of  21 variables:
##  $ V1 : Factor w/ 4 levels "A11","A12","A13",..: 1 2 4 1 1 4 4 2 4 2 ...
##  $ V2 : int  6 48 12 42 24 36 24 36 12 30 ...
##  $ V3 : Factor w/ 5 levels "A30","A31","A32",..: 5 3 5 3 4 3 3 3 3 5 ...
##  $ V4 : Factor w/ 10 levels "A40","A41","A410",..: 5 5 8 4 1 8 4 2 5 1 ...
##  $ V5 : int  1169 5951 2096 7882 4870 9055 2835 6948 3059 5234 ...
##  $ V6 : Factor w/ 5 levels "A61","A62","A63",..: 5 1 1 1 1 5 3 1 4 1 ...
##  $ V7 : Factor w/ 5 levels "A71","A72","A73",..: 5 3 4 4 3 3 5 3 4 1 ...
##  $ V8 : int  4 2 2 2 3 2 3 2 2 4 ...
##  $ V9 : Factor w/ 4 levels "A91","A92","A93",..: 3 2 3 3 3 3 3 3 1 4 ...
##  $ V10: Factor w/ 3 levels "A101","A102",..: 1 1 1 3 1 1 1 1 1 1 ...
##  $ V11: int  4 2 3 4 4 4 4 2 4 2 ...
##  $ V12: Factor w/ 4 levels "A121","A122",..: 1 1 1 2 4 4 2 3 1 3 ...
##  $ V13: int  67 22 49 45 53 35 53 35 61 28 ...
##  $ V14: Factor w/ 3 levels "A141","A142",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ V15: Factor w/ 3 levels "A151","A152",..: 2 2 2 3 3 3 2 1 2 2 ...
##  $ V16: int  2 1 1 1 2 1 1 1 1 2 ...
##  $ V17: Factor w/ 4 levels "A171","A172",..: 3 3 2 3 3 2 3 4 2 4 ...
##  $ V18: int  1 1 2 2 2 2 1 1 1 1 ...
##  $ V19: Factor w/ 2 levels "A191","A192": 2 1 1 1 1 2 1 2 1 1 ...
##  $ V20: Factor w/ 2 levels "A201","A202": 1 1 1 1 1 1 1 1 1 1 ...
##  $ V21: int  1 2 1 1 2 1 1 1 1 2……

首先加载neuralnet包尝试一下,只用数值型变量建模,没有报错。

library("neuralnet")
NNModelAllNum <- neuralnet(V21 ~ V2 + V5 + V8, data)
NNModelAllNum

当我们把V1放入解释变量中出现了如下错误

NNModel <- neuralnet(V21 ~ V1 + V2 + V5 + V8, data)
## Error: 需要数值/复数矩阵/矢量参数

此时可以用model.matrix函数将V1转化为三个虚拟变量,V1A12,V1A13,V1A14。

>dummyV1 <- model.matrix(~V1, data)
>head(cbind(dummyV1, data$V1))
   (Intercept) V1A12 V1A13 V1A14
 1           1     0     0     0 1
 2           1     1     0     0 2
 3           1     0     0     1 4
 4           1     0     0     0 1
 5           1     0     0     0 1
 6           1     0     0     1 4

因为model.matrix函数对数值型和分类Level=2的类别型变量没有影响,所以可以将四个变量一起用该函数生成新的数据集modelData,就可以用该数据集建模了。

>modelData <- model.matrix(~V1 + V2 + V5 + V8 + V21, data)
>head(modelData)
   (Intercept) V1A12 V1A13 V1A14 V2   V5 V8 V21
 1           1     0     0     0  6 1169  4   1
 2           1     1     0     0 48 5951  2   2
 3           1     0     0     1 12 2096  2   1
 4           1     0     0     0 42 7882  2   1
 5           1     0     0     0 24 4870  3   2
 6           1     0     0     1 36 9055  2   1

另一种方法是来自nnet package的class.ind函数

>library("nnet")
>dummyV12 <- class.ind(data$V1)
>head(dummyV12)
      A11 A12 A13 A14
 [1,]   1   0   0   0
 [2,]   0   1   0   0
 [3,]   0   0   0   1
 [4,]   1   0   0   0
 [5,]   1   0   0   0
 [6,]   0   0   0   1

可以看到,该结果和model.matrix稍有区别,生成了四个虚拟变量。要注意,为了避免多重共线性,对于level=n的分类变量只需选取其任意n-1个虚拟变量。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • R语言编码问题的解决

    今天博客主要是解决一个学R语言里面最最痛苦的问题(嗯,python2.x里面也有),就是中文乱码问题: 一般用R语言的同学,多半遇见过以下这个问题: 反正虾神我每次遇见这个问题,立刻就是: 实际上这个问题写代码的人一般都能遇见,不同字符编码的问题,如果是从文件里面读的还好说,可以带这个字符编码集一起读,但是如果这个数据是来自于数据库的,如果经验的话,那就真得各种凉拌了. 下面我简单把我今天通过R语言从Postgresql数据库中处理中文问题的整个流程说说,如果哪位同学也遇上了,可以参考我的整个解

  • R语言-实现按日期分组求皮尔森相关系数矩阵

    R语言按日期分组求相关系数 前几天得到了3700+支股票一周内的波动率,想要计算每周各个股票之间的相关系数并将其可视化.最终结果保存在制定文件夹中. 部分数据如下: 先读取数据 data<-read.csv("D:/data/stock_day_close_price_week_series.csv", header = TRUE,blank.lines.skip = TRUE) 利用mice包处理缺失值: library(lattice) library(MASS) libra

  • R语言差异检验:非参数检验操作

    非参数检验是在总体方差未知或知道甚少的情况下,利用样本数据对总体分布形态进行推断的方法.它利用数据的大小间的次序关系(秩Rank),而不是具体数值信息,得出推断结论. 它是参数检验所需要的某些条件不满足时所使用的方法. 和参数检验相比,非参数检验的优势如下: 稳健性.对总体分布的条件要求放宽 对数据类型要求不严格,适用有序分类变量 适用范围广 劣势: 没有利用实际数值,损失了部分信息,检验的有效性较差. 非参数性检验的方法非常多,基于方法的检验功效性角度,本文只涉及 双独立样本:Mann-Whi

  • R语言变量级别的数据处理操作

    变量级别的数据处理无非是对变量的增删改查. 增 即增加新的变量 R语言中,增加一个新变量形式语句如下: 变量名 <- 表达式 表达式可以包含多种运算符和函数.常见运算符包括: 运算符 描述 + 加 - 减 * 乘 / 除 ^或** 求幂 x%%y 求余(x mod y).5%%2的结果为1. x%/%y 整数除法.5%/%2的结果为2. 示例: #创建一个数据框 mydata <- data.frame(x1 = c(2,2,6,4), + x2 = c(3,4,2,8)) mydata x1

  • R语言变量重编码、重命名的操作

    1.变量重编码 重编码涉及根据同一个变量和/或其他变量的现有值创建新值的过程,如将符合某个条件的值重新赋值等,这里主要介绍两种常见的方法: #第一种方法 per <- data.frame(name = c("张三","李四","王五","赵六"), age = c(23,45,34,1000)) per per$age[per$age == 1000] <- NA #设置缺失值 per$age1[per$age

  • R语言操作X轴日期实例讲解

    R语言操作X轴日期: 需要用到程序包library(lubridate):程序包是在R的安装包C:\R-3.4.4\bin\x64\RGui.exe里根据命令安装的 将日期改为xxxx/xx/01: firstDay='2020/02/12' : 可用 day(firstDay)<-01; //此时firstDay的数据为:'2020/02/01':day()是获取日,month()获取月份,year()获取年份 都需要'lubridate'包 可以通过write.table(firstDay,

  • R语言实现将分类变量转换为哑变量(dummy vairable)

    生成测试数据 a1 <- c("f","f","b","b","c,"c") 利用nnet包中的函数class.ind > class.ind(a1) b c f [1,] 0 0 1 [2,] 0 0 1 [3,] 1 0 0 [4,] 1 0 0 [5,] 0 1 0 [6,] 0 1 0 class.ind代码 class.ind <- function(cl) { n &

  • R语言glmnet包lasso回归中分类变量的处理图文详解

    我们在既往文章<手把手教你使用R语言做LASSO 回归>中介绍了glmnet包进行lasso回归,后台不少粉丝发信息向我问到分类变量处理的问题,我后面查了一下资料之前文章分类变量没有处理,非常抱歉.现在来重新聊一聊分类变量的处理. 我们导入glmnet包的时候可以看到,还需要导入一个Matrix包,说明这个矩阵包很重要 按照glmnet包的原文如下: 就是告诉我们,除了Cox Model外,其他的表达都支持矩阵形式,在Cox Model的介绍中,函数样式为 说明我们应该把其他变量变为矩阵的形式

  • R语言数据可视化tidyr与ggplot2多个变量分层展示举例实现

    目录 每个变量的密度分布情况 思考 tidyr ggplot2进行绘图 在R语言普通的绘图中,使用par()参数可以在一张图上实现不同变量的子图.如果我们想要用ggplot2实现,则需要整理我们的原始数据,这通常是非常麻烦的,这时就需要用到我们的tidyr来帮助我们绘图. 可能说上面一段话不是很容易理解,下面我们来举个栗子. 每个变量的密度分布情况 y1 <- rnorm(20) y2 <- rnorm(20) dat <- data.frame(y1, y2) 现有的数据集: y1 y

  • R语言常见面试题整理

    尊敬的读者,这些R语言面试题是专门设计的,以便您应对在R语言相关面试中可能会被问到的问题. 根据我的经验,良好的面试官几乎不打算在你的面试中问任何特定的问题,通常都是以如下的问题为开端进一步展开后继的问题. 什么是R语言编程? R语言是一种用于统计分析和为此目的创建图形的编程语言.不是数据类型,它具有用于计算的数据对象.它用于数据挖掘,回归分析,概率估计等领域,使用其中可用的许多软件包. R语言中的不同数据对象是什么? 它们是R语言中的6个数据对象.它们是向量,列表,数组,矩阵,数据框和表. 什

  • R语言关于生存分析知识点总结

    生存分析处理预测特定事件将要发生的时间. 它也被称为故障时间分析或分析死亡时间. 例如,预测患有癌症的人将存活的天数或预测机械系统将失败的时间. 命名为survival的R语言包用于进行生存分析. 此包包含函数Surv(),它将输入数据作为R语言公式,并在选择的变量中创建一个生存对象用于分析. 然后我们使用函数survfit()创建一个分析图. 安装软件包 install.packages("survival") 语法 在R语言中创建生存分析的基本语法是 Surv(time,event

  • R语言关于变量的知识点总结

    变量为我们提供了我们的程序可以操作的命名存储. R语言中的变量可以存储原子向量,原子向量组或许多Robject的组合. 有效的变量名称由字母,数字和点或下划线字符组成. 变量名以字母或不以数字后跟的点开头. 变量名 合法性 原因 var_name2. 有效 有字母,数字,点和下划线 VAR_NAME% 无效 有字符'%'.只有点(.)和下划线允许的. 2var_name 无效 以数字开头 .var_name, var.name 有效 可以用一个点(.),但启动点(.),不应该后跟一个数字. .2

  • R语言将变量分组的3种方法实例(含cut函数说明)

    目录 前言 方法一:直接对分组变量进行赋值 方法二:使用within函数对变量进行分组 方法三:采用cut函数 总结 前言 在数据处理的过程中,我们有时候需要将连续的数值数据转换为类别数据,比如将收入分成高.中和低三组,将学生成绩分为优.良.中.及格和不及格五组. 本来将基于R语言,采用三种方法来实现:第一种是对变量直接进行重新赋值,第二种是使用within函数对语句进行组织,第三种是cut函数. 首先我们定义一个数据框,这个数据框包括学生姓名和数学成绩两个变量. #定义数据框 mathScor

  • R语言利用loess如何去除某个变量对数据的影响详解

    R语言介绍 R语言是用于统计分析,图形表示和报告的编程语言和软件环境. R语言由Ross Ihaka和Robert Gentleman在新西兰奥克兰大学创建,目前由R语言开发核心团队开发. R语言的核心是解释计算机语言,其允许分支和循环以及使用函数的模块化编程. R语言允许与以C,C ++,.Net,Python或FORTRAN语言编写的过程集成以提高效率. R语言在GNU通用公共许可证下免费提供,并为各种操作系统(如Linux,Windows和Mac)提供预编译的二进制版本. R是一个在GNU

  • R语言变量赋值深入讲解

    变量可以使用向左,向右且等于操作符来分配值.可以使用 print() 或 cat() 函数打印变量的值.cat() 函数将多个项目并成连续并打印输出. # Assignment using equal operator. var.1 = c(0,1,2,3) # Assignment using leftward operator. var.2 <- c("learn","R") # Assignment using rightward operator. c

随机推荐