文章目录
一、因子与水平
在R中可以简单地看作一个附加了更多信息的向量(它们内部机理不同)。额外的信息包括向量中不同值得记录,称为“水平”:
> x<-c(5,12,13,12)
> xf<-factor(x)
> xf
[1] 5 12 13 12
Levels: 5 12 13
xf中的不同数值(5、12、13)就是水平
> str(xf)
Factor w/ 3 levels "5","12","13": 1 2 3 2
> unclass(xf)
[1] 1 2 3 2
attr(,"levels")
[1] "5" "12" "13"
这里xf的核心不是(5,12,13,12)而是(1,2,3,2)
后者意味着我们的数据是由水平1的值、接着水平2和水平3的值,最后是水平2的值构成。
- 因子的长度定义为数据的长度,而不是水平的个数
> xf
[1] 5 12 13 12
Levels: 5 12 13
> length(xf)
[1] 4
- 可以提前插入新的水平
> x<-c(5,12,13,12)
> xff<-factor(x,levels = c(5,12,13,88))
> xff
[1] 5 12 13 12
Levels: 5 12 13 88
> xff[2]<-88
> xff
[1] 5 88 13 12
Levels: 5 12 13 88
二、因子的常用函数
1、tapply函数
来一个例子:
> ages <- c(25,26,55,37,21,42)
> affils <- c("R","D","D","R","U","D")
> tapply(ages,affils,mean)
D R U
41 31 21
函数tapply()把向量(“R”,“D”,“D”,“R”,“U”,“D”)作为具有水平"D"、"R"和"U"的因子。注意到“D”出现在索引2、3、6的位置;"R"出现在索引1、4的位置,“U"出现在索引5的位置tapply()分别计算三个索引向量的mean(),并将这些均值返回到三元向量,该向量的元素名称分别为"D”、“R”、“U”,反映出tapply()函数所调用的因子水平。
如果有两个或者两个以上的因子呢?
> d <- data.frame(list(gender=c("M","M","F","M","F","F"),
+ age=c(47,59,21,32,33,24),income=c(55000,88000,33000,77000,11000,66000)))
> d
gender age income
1 M 47 55000
2 M 59 88000
3 F 21 33000
4 M 32 77000
5 F 33 11000
6 F 24 66000
> d$over25<-ifelse(d$age>25,1,0)
> d
gender age income over25
1 M 47 55000 1
2 M 59 88000 1
3 F 21 33000 0
4 M 32 77000 1
5 F 33 11000 1
6 F 24 66000 0
> tapply(d$income,list(d$gender,d$over25),mean)
0 1
F 49500 11000.00
M NA 73333.33
我们设定了两个因子,一个是性别,另一个是指示变量,表征年龄是否大于25。由于这两个因子每个都有两个水平,tapply()会将收入数据分为四组,每一组代表性别和年龄的一种组合,然后对每一组应用函数mean()。
2、split()函数
tapply()是将向量分割为组,然后针对每个组应用指定的函数,split()只是形成分组
基本形式:split(x,f),x为向量或数据框,f为因子或因子的列表。该函数可以把x划分为组,并返回分组的列表(注意,x在split()中可以是数据框,而在tapply()中不可以)
> d
gender age income over25
1 M 47 55000 1
2 M 59 88000 1
3 F 21 33000 0
4 M 32 77000 1
5 F 33 11000 1
6 F 24 66000 0
> split(d$income,list(d$gender,d$over25))
$F.0
[1] 33000 66000
$M.0
numeric(0)
$F.1
[1] 11000
$M.1
[1] 55000 88000 77000
split()的输出是一个列表
3、by()函数
tapply()函数的第一个参数必须是向量,然而回归的的输入是一个至少两列的矩阵(或数据框):一列是被预测的变量,另一列或多列是预测变量。
这里可以使用by()函数。它与tapply()(实际上它是在内部调用)的运作方式类似,但by()应用于对象而不仅是向量
- by()的调用方式看上去与tapply()非常相似,第一个参数指定数据,第二个为分组因子,第三个是应用于每组的函数
三、表的操作
举个例子
> u<-c(22,8,33,6,8,29,-2)
> fl<-list(c(5,12,13,12,13,5,13),c("a","bc","a","a","bc","a","a"))
> tapply(u, fl, length)
a bc
5 2 NA
12 1 1
13 2 1
函数tapply()临时将向量划分成6个子向量,然后把函length()应用到每个子向量(求长度的运算不依赖于u有什么元素,所以只用关注因子),那些子向量的长度是两个因子的6种组合中每种情况的出现次数
然而,在此例子中存在一个问题:缺失值NA,事实上这个值应该为0,用table()函数创立表:
> table(fl)
fl.2
fl.1 a bc
5 2 0
12 1 1
13 2 1
1、表中有关矩阵和类似数组的操作
正如大多数(非数学的)矩阵/数组运算可以用在数据框上,这些运算也能用在表中
- 可以使用矩阵符号来访问表的单元格频数
- 可以用标量乘以这个矩阵
- R提供一个函数addmargins()来解决计算边际值得问题
- 函数dimnames()获得维度得名称和水平值
四、其他与因子和表有关的函数
1、aggregate()函数
aggregate()函数对分组中的每一个变量调用tapply()函数