R语言的因子实现统计功能,因此称为R语言的先锋不为过份。因子用以数据分类,它有两个内容,一是数据,二是数据的分类,称为水平levels。列表类似C语言的结构struct,元素可选择任意数据结构,是R语言数据结构在类型上的“开拓”。

2.4.1 因子factor

分类变量刻画数据的细分属。统计分析常用分类,在R中称为因子(factor)。因子应用统计学的名义变量(nominal variable)和有序变量,功能是记载数据的分组和分类,是R语言统计功能的基础。因子有辅助信息水平(levels)作为分类集合,因子的元素是不同值的levels集元素。水平可为分类设置有意义的标签。

因子的水平是分类信息,然而分类并不表示有序,例如:疾病有循环系统、肺部、消化系统疾病,没有先后、程度、轻重的区别,称为名义型类别变量。而人的健康有疾病、疲劳(亚健康)、健康、身体素质好,这四种程度是有顺序的。因此因子具有普通因子和有序因子两个类型。

应用因子生成更有意义的summary()统计信息。

1.创建因子

    函数factor()创建数据集所有元素的分类。为数据框创建因子是良好的编程习惯,创建向量的因子的标准格式:

    factor(vector,levels=c(),ordered=TRUE)

参数levels定义水平集合,是一个整数向量,ordered表示有序分类,区分普通因子和有序因子。

eg1.创建向量的因子

>dv1=c(1,10,13,10)
>df1=factor(dv2)   #factor()将dv1向量的元素进行分类,创建因子df1 
>df1   
[1] 1 10 13 10   #因子的元素
levels: 1 10 13   #levels集
>str(df1)    #df1的内部结构
 Factor w/3 levels:”1” “10” “13”:1 2 3 2  #分成三类:1,10,13

    as.factor()可将数据转换为因子。

2.数据管理

     length()是因子的长度,保存因子元素的数量而不是levels集的数量。

3.因子的操作

(1)设置有意义的levels集元素

当一个向量不允许有重复值时,因子可以查看分类的错误。

eg2.1 levels()提取水平的名称

>pain=c(0,3,2,2,1)  #《R语言统计入门》p15的例子,对医学数据的操作
>fpain=factor(pain,levels=0:3)  #创建pain的因子,水平的编码0:3
>levels(fpain)=c("none","mild","medium","severe")

以上例题为因子fpain的水平设置有意义的标签,则fpain的元素将用标签代替。

(2)因子元素与分类的关系

eg2.2 因子的操作

>fpain
[1] none severe medium medium mild
Levels: none mild medium severe
>as.numeric(fpain)  #将fpain的元素转换为整数
[1] 1 4 3 3 2       #数值从1开始
>levels(fpain)
[1] "none","mild","medium","severe"

以上程序表明as.numeric()只能转换因子fpain的元素,却不能处理levels集。

(3)分类水平的合并

    若某一个分类的观测少不能有效统计,则将两个水平合并到一个新的因子水平中。

>ftpain1=fpain
>levels(fpain)=list(none="none",
                intermediate=c("mild","medium"),
                severe="severe")   #合并分类用列表实现
>levels(fpain)
[1] "none","intermediate","severe"

(4)有序因子

eg3.创建医学数据的有序因子

>patientID=c(1,2,3,4)  #每个病人的ID号不同
>statu=c(“Poor”,”Excellent”,”Improved”,”Improved”)         #病情
>patientdata=data.frame(patientID,statue)  #先建立数据框,再建立因子
>fstat=factor(statu,levels=c(“Poor”,”Improved”,”Excellent”),ordered=TRUE)
                          #有序因子,词语是有序的
>str(fstat)
 ord.factor w/ 3 levels "Poor"<"Improved"<..: 1 3 2 2  #”<”表示有序因子
>patiendata$fstat=fstat
> summary(patientdata)  #summary()中可知每个分类的元素数量
   patientID          status        fstatu  #有序因子
 Min.   :1.00     Excellent:1      Poor    :1    #有一个病人情况不好
 1st Qu.:1.75      Improved :2     Improved :2    #两个病人病情好转
 Median :2.50     Poor    :1      Excellent:1    #有一个病人几乎痊愈
 Mean   :2.50                              
 3rd Qu.:3.25                              
 Max.   :4.00 
> unclass(patientdata)
$patientID
[1] 1 2 3 4
$status??????????
[1] Poor   Excellent Improved  Improved 
Levels: Excellent Improved Poor
$fstat
[1] Poor   Excellent Improved  Improved 
Levels: Poor < Improved < Excellent

参数ordered很有意义,应掌握使用方法。

3.因子的应用

(1)数据框设置因子变量

在数据框中生成重要的变量的因子,为接下来的数据分析做好准备。

将ISwR软件包的医学数据集thuesen的血糖含量设置分类{1,2,3,4,5,6,7,8,9,10,11,12},1对应[0,1.0)的变量值,...,12对应[11.0,12.0)。了解血糖的范围可用函数range()。源程序见eg4.

eg4.设置数据框变量的因子

>library(ISwR)
>data(thuesen)
>dim1=dim(thuesen)
>dim1
[1] 24  2
>thuesen
##          blood.glucose  short.velocity
##1           15.3           1.76
##2           10.8           1.34
##3            8.1           1.27
##4           19.5           1.47
##5            7.2           1.27
##6            5.3           1.49
##7            9.3           1.31
##8           11.1           1.09
##9            7.5           1.18
##10          12.2           1.22
##11           6.7           1.25
##12           5.2           1.19
##13          19.0           1.95
##14          15.1           1.28
##15           6.7           1.52
##16           8.6            NA
##17           4.2           1.12
##18          10.3           1.37
##19          12.5           1.19
##20          16.1           1.05
##21          13.3           1.32
##22           4.9           1.03
##23           8.8           1.12
##24           9.5           1.70
>range(thuesen[1])
[1]  4.2  19.5
>levels=seq(4,20,1)  #4,20是range的整数
>levl=length(levles)
>ln=dim1[1]
>fthues=factor(1:ln,levels)
>fthues
##[1] <NA> <NA> <NA> 4    5    6    7    8    9    10   11   12   13   14  
##[15] 15   16   17   18   19   20   <NA> <NA> <NA> <NA>
Levels: 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
> typeof(fthues) #数据类型
[1] "integer"
> class(fthues)  #类型
[1] "factor"
> str(fthues)  #fthues内部结构
 Factor w/ 16 levels "4","5","6","7",..: 12 7 5 16 4 2 6 8 4 9 ...
                  #可用循环语句实现而不是简单罗立
>for(i in 1:levl-1)    #i是向量levels的下标,不可与levels元素的值混淆
                  #i=1,levels[i]=4;i=2,levels[i]=5
{  
logthes=thuesen$blood.glu<levels[i+1]$thuesen$blood.glu>=levels[i]
                  #logthes是逻辑向量,表示下标有效的逻辑值
                  #levels[levl]=20是为编程设置的一个值,无实际意义
fthues[logthes]=levels[i]  
                  #fthues[logthes]不等于levels的下标i,应仔细不可疏忽
}
>fthues
##[1] 15 10 8  19 7  5  9  11 7  12 6  5  19 15 6  8  4  10 12 16 13 4  8  9 
##Levels: 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
>fthues=factor(fthues,levels=seq(4,19,1),ordered=TRUE)
>str(fthues)
 ord.factor w/ 16 levels "4"<"5"<"6"<"7"<..: 12 7 5 16 4 2 6 8 4 9 ...
>thuesen$fthues=fthues  
>summary(thuesen)
 blood.glucose      short.velocity      fthues    #因子fthues频数的统计
 Min.   : 4.200     Min.   :1.030       8      : 3  
 1st Qu.: 7.075      1st Qu.:1.185        4      : 2  
 Median : 9.400     Median :1.270       5      : 2  
 Mean   :10.300    Mean   :1.326     6      : 2  
 3rd Qu.:12.700     3rd Qu.:1.420       7      : 2  
 Max.   :19.500     Max.   :1.950     9      : 2

 

对数据框的变量设置因子,可用summary()统计每一类的元素数量,并且可应用tapply()函数对每一个进行相同的计算f()。

(2)线性回归的应用

因子在线性回归函数的数据拟合中应用,使得输出变短。因子的统计信息可用汇总统计函数summary()表示。函数summary()体现数据框所有变量的汇总信息,显示数值连续型变量的最小值、最大值、均值和各四分位数,factor变量各水平的频数值。因此,因子变量的应用在线性回归函数lm()的统计信息中,可使输出更短小精悍。

>summary(thuesen)

4.因子的函数

unclass()显示因子的分类,而且有attr()等。

>unclass(df1)
[1] 1 2 3 2
>unclass(fthues)
>unclass(pathtiendata$fstatu)
5.tapply()应用和factor因子
eg5. tapply(data,index,f())的应用
> ages <-c(26,28,56,38,25,42)  
> affits <-c("R","D","D","R","U","D")  #用途类似levels,但是没有生成factor
>tapply(ages,affits,means)  #应用affits对ages向量进行分类,计算每类的means
     D     R    U
    42    32   25

函数tapply()把向量affits当作因子,levels={"D","R","U"},”D”出现在下标2,3,6的位置,”R”出现在1,4的位置,”U”出现在5。因此,ages向量的分组是(26,55,42),(25,37),(21)。然后,tapply()对所有分组计算means均值,分别是41,31,21。此编程方法是对数据设置向量作为因子,因此并不是根据数据的可管理特性应用factor()进行分类,而是根据实际应用的要求。不能用factor()对向量元素进行分类时可用此方法,但是对大量数据设置每个元素的分类则很费力,例如ISwR软件包的thuesen数据集。

函数tapply()的功能是,根据分类向量levels分组数据向量data,可得到多个分组数据,然后对所有分组应用函数f()。因此tapply()函数可不需要对数据框的不同变量应用计算f(),而是对不同长度的分组数据应用计算f()。 

2.4.2 列表list

列表(list)像C的结构struct或python语言的字典类型。列表的组件(components)称为分量或元素,组件名则为标签tags。R语言数据框和面向对象编程的基础是列表。列表元素的长度可不相同,类型可是单元素或者列表,因此在递归型recursive数据结构的基础上看,列表是数据结构中的广义表。

1. 创建列表

向量、矩阵、数据框、列表。列表是R语言多数函数的返回值类型,因此R语言函数可返回多个值组成一个列表,与C语言不同。list()的标准格式:

list(tag1=compon1,tag2=compon2,...,tagR=componR)

    列表的常用应用有多维数组的标签,添加数据框的观察,以及构成实际的报表格式。创建列表还可用函数vector(),参数mode=list。

eg1.三维数组标签的产生

   

dim1=c(“A1”,”A2”,”A3”)
      dim2=c(“B1”,”B2”)
      dim3=c(“C1”,”C2”,”C3”)
      dimnames=list(dim1,dim2,dim3)

eg2.列表构成的报表

字符串,gs=”This is 2016 fist list”

报表的主要对象:一个数值型向量,ha=c(20,29,39,43)

报表的主要内容:一个矩阵,salaryM=matrix(1:10,nrow=5)

报表的注释:一个字符型向量,notes=c(“one”,”two”,”three”)

则,生成报表,dlist1=list(Title=gs,age=ha,salaryM,notes)。

只有前两个组件有标签。组件的编号又称为索引。? 

eg3.用vector()创建列表,因为列表是向量。

>dlist2=vector(mode=list)
>dlist2[["events"]]=c("writing Docx ","studying","research")
>dist2
$events
[1]  "writing Docx"  "studying"   "research"

2.数据管理

    数据类型 mode()、列表组件个数 length()、获得标签 names()。

3.列表组件的访问

   选取列表组件的方法有三个,list$标签,list[["标签"]],list[[组件编号]]。若要访问分量中的元素,则用list[[组件编号]][元素下标范围s:t]或list$[组件名][s:t]。元素下标范围同样可用条件选择的方法。

>dlist2[[1]]
[1]  "writing Docx"  "studying"   "research" 
>dlist2[[1]][2:3]
[1]  "studying"   "research"

 

4.数据操作

(1)增加列表组件

方法一,组件赋值dlist2$timecha=c("Lqm","Lih","Sh"),方法二,组件下标索引赋值dlist2[[3]]=c(20,20,20,100,100,30),则列表dlist2有三个组件。

(2)删除列表元素

    将列表组件设置为NULL,应注意此元素后面组件的下标索引都减1。

(3)生成子列表[]

    用list["标签"]和list[组件编号]返回子列表,而list[[]]访问组件,返回组件的类型。

>dlist3=dlist2[2]   #此方法类似数据框[列下标]
>class(dlist3)
[1]  "list"
>dlist3
$timecha
[1]  "Lqm"  "Lih"  "Sh"

(4)c()拼接合并多个列表

   然而c()合并的列表中,组件的层次相同。若要保持组件是一个列表,应用list()更恰当。

>dlist4=c(list("tomorrow",2016-10-19,5),list(read,writing))  
>class(dlist4)
[1]  "list"
>length(dlist4)
[1] 5
>dlist4
>str(dlist4)
>dlist5=list(list("tomorrow",2016-10-19,5),list(read,writing))
>str(dlist5)

 

5.列表的函数

(1)unlist()

unlist()把列表转换为向量,获取列表的值,而且此向量的元素有标签。去掉元素标签用函数unnames()。若列表元素是字符串则unlist()的返回值是字符串,若列表元素都是数值型则产生数值向量。若两类元素都有或者列表元素类型不同,则执行强制转换,生成大多数元素的类型,例如字符串。

>dv1=unlist(dlist4)
>class(dv1)
[1] character
>length(dv1)
[1] 5

6.应用apply族函数 

 

7.类型转换

    is.recursive(x)可判断列表是否递归类型。Is.list()可发现函数的返回值是否列表。as.list()转换产生列表。