R语言系列第三期:③R语言表格及其图形展示
本文首发于 ”百味科研芝士“ 微信公众号,转载请注明:百味科研芝士,Focus科研人的百味需求
点击蓝字关注我们
分类数据通常以表格的形式来描述。这一部分就来为大家介绍如何用你的数据创建一个表格及计算相关的频率。
A. 生成表格
一个双向表格可以作为一个矩阵对象输入。Altman给出了一个关于分娩妇女在不同婚姻状态下咖啡因消耗的例子。表格可以这样输入:
> mar<-c(652,1537,598,242,36,46,38,21,218,327,106,67)
> caff.marital<-matrix(mar,nrow=3,byrow=T)
> caff.marital
[,1] [,2] [,3] [,4]
[1,] 652 1537 598 242
[2,] 36 46 38 21
[3,] 218 327 106 67
#Tips:nrow和ncol中的一个被明确给出,则R会计算相应的另一个,从而使得矩阵中的数值与输入的值数目相匹配。其实,当两个参数都给出来之后,即使数据的数目不匹配,给出的值将被循环使用,但是R可能会给出警告。
当然我们为了可读性,需要给矩阵添加横纵标目的名称:
> colnames(caff.marital)<-c("0","1-150","150-300",">300")
> rownames(caff.marital)<-c("Married","Divorced","Single")
> caff.marital
0 1-150 150-300 >300
Married 652 1537 598 242
Divorced 36 46 38 21
Single 218 327 106 67
另外,可以添加行标题和列标题:
> names(dimnames(caff.marital))<-c("marital","consumption")
> caff.marital
consumption
marital 0 1-150 150-300 >300
Married 652 1537 598 242
Divorced 36 46 38 21
Single 218 327 106 67
其实我们可以发现,这里的所有的数字都不是指代实际值,而是表示相同类型数据的频数。这一类的表格不完全等同于矩阵,R里有一个“table”类能更好地描述它。你可以使用as.table(caff.marital)把上面的矩阵转换成表格类:
> as.data.frame(as.table(caff.marital))
marital consumption Freq
1 Married 0 652
2 Divorced 0 36
3 Single 0 218
4 Married 1-150 1537
5 Divorced 1-150 46
6 Single 1-150 327
7 Married 150-300 598
8 Divorced 150-300 38
9 Single 150-300 106
10 Married >300 242
11 Divorced >300 21
12 Single >300 67
#Tips:这里需要转换成数据框才能展示出来freq变量,因为矩阵只是二维的一个交叉表且内部数据一致。而数据框是可以展示table的详细数据的。as.是一个强大的前缀函数,它可以实现很多功能的转换,比如说as.character()就可以把数值型向量转换成字符型向量。
数据集juul前面已经用过了(ISwR包),这里我们来看一下数据集里的其他变量,比如sex和menarche(表明一个女孩是否有了第一次生理期):
> attach(juul)
> juul<-transform(juul,
+ sex=factor(sex,labels=c("M","F")),
+ menarche=factor(menarche,labels=c("NO","YES")),
+ tanner=factor(tanner,labels=c("I","II","III","IV","V")))
> table(sex)
sex
1 2
621 713
> table(sex,menarche)
menarche
sex 1 2
1 0 0
2 369 335
#Tips:如果需要对单个变量做频数的分析,只需要在table()括号内添加单个变量,如果需要做成交叉表,那么就可以按照行,列的顺序添加需要探索的两个变量。当然要研究3个及以上的变量也可以,只需要在之后罗列变量并以“,”隔开即可。
另外,与table()同源的另外的几个函数还有xtabs(),ftable(),它们通常会用来对数字向量和因子变量制表,但是它们与table()不同,将转化后的水平自动作为行和列的名称。因此,建议将数字编码的分类变量转化成因子。
Xtabs()非常类似table(),它使用单边模型公式接口:
> xtabs(~tanner+sex,data=juul)
sex
tanner M F
I 291 224
II 55 48
III 34 38
IV 41 40
V 124 204
#Tips:模型公式接口是建立模型函数(如lm(),glm()等)常用的参数,往往“~”左侧放入的是因变量,右侧为自变量,而data参数指示数据的来源。
但是,有的时候得到的多向表的形式并不是很友好:
> head(stroke)
> xtabs(~dgn+diab+coma,data=stroke)
, , coma = No
diab
dgn No Yes
ICH 53 6
ID 143 21
INF 411 64
SAH 38 0
, , coma = Yes
diab
dgn No Yes
ICH 19 1
ID 23 3
INF 23 2
SAH 9 0
增加维度之后会得到更多的二维表格,往往结果会很长,所以这时候就可以用ftable()了,这个函数可以创造出一个扁平的表格来:
> ftable(coma+diab~dgn,data=stroke)
coma No Yes
diab No Yes No Yes
dgn
ICH 53 6 19 1
ID 143 21 23 3
INF 411 64 23 2
SAH 38 0 9 0
#Tips:注意的是,这里的公式改变了,~左侧表示的是顶端的分类,而~的右侧是左侧分类。这样就可以叠放到一起了。可以尝试更多的方式呈现出来结果各不相同。
和矩阵一样,表也可以转置,t()函数:
> t(caff.marital)
marital
Consumption Married Divorced Single
0 652 36 218
1-150 1537 46 327
150-300 598 38 106
>300 242 21 67
#Tips:多维数据的转置使用aperm()函数,可以参考帮助文件,这里不多介绍。
B. 表格的合计和比例
很多时候我们需要计算表格的边际合计值,我们可以使用margin.table()函数来实现:
> tanner.sex<-xtabs(~tanner+sex,data=juul)
> tanner.sex
sex
tanner M F
I 291 224
II 55 48
III 34 38
IV 41 40
V 124 204
然后我们计算边际表格:
> margin.table(tanner.sex,1)
tanner
I II III IV V
515 103 72 81 328
> margin.table(tanner.sex,2)
sex
M F
545 554
#Tips:这个函数第二个参数是边际下标数字:1,2分别代表求行,列的合计。
需要求比例的时候可以使用:
> prop.table(tanner.sex,1)
sex
tanner M F
I 0.5650485 0.4349515
II 0.5339806 0.4660194
III 0.4722222 0.5277778
IV 0.5061728 0.4938272
V 0.3780488 0.6219512
#Tips:这个函数只能计算占当前方向的比例,不能表示占总体的数据情况,但是你可以写:
> tanner.sex/sum(tanner.sex)
sex
tanner M F
I 0.26478617 0.20382166
II 0.05004550 0.04367607
III 0.03093722 0.03457689
IV 0.03730664 0.03639672
V 0.11282985 0.18562329
#Tips:同样,margin.table() 和prop.table()也可以对多维表格操作。并且margin.table()的参数可以是个向量。
C. 表格的图形显示
出于直观的目的,可能会希望展示一幅图而不是一个由数字组成的表格。
① 条形图
barplot()用来画条形图。这个函数第一个参数,可以使用向量或者矩阵:
> total.caff<-margin.table(caff.marital,2)
> total.caff
consumption
0 1-150 150-300 >300
906 1910 742 330
> barplot(total.caff,col="white")
#Tips:默认是输出灰色图形,可以通过col参数来调整任意颜色。
另外如果条形图里的参数不是一个向量,而是一个矩阵,那么它默认创建一个“堆积条形图”,每列根据表中不同的行的贡献被分割。如果希望全部分散开来显示,那么可以使用参数beside=T来实现:
> par(mfrow=c(2,2))
> barplot(caff.marital)
> barplot(t(caff.marital))
> barplot(t(caff.marital),beside=T)
> barplot(prop.table(t(caff.marital),2),beside=T)
> par(mfrow=c(1,1))
#Tips:后三幅图我们用了转置,最后一图列表达的是组中每个分类的构成比,因此婚姻状态的相对大小的信息就损失了,但是通过图2/3可以看出各婚姻状态组间比例。
美化图形的方法很多,这里举个例子(+图例):
> barplot(prop.table(t(caff.marital),2),beside=T,
+ legend.text=colnames(caff.marital),
+ col=c("white","grey80","grey50","black"))
#Tips:legend.text参数是对图例的文字说明,col指代颜色,”grey80”代表灰度80%。我们可以看到图例和图形顶端有重叠,这是因为R没有给图例单独的位置,需要使用locator()函数定位到右上角或相应位置,然后使用legend()函数明确插入位置就可以实现图例的完全控制。
② 点图
其实跟条形图类似,它与带有参数beside=T的条形图包含相同的信息,但给出了不同的视觉效果:
> dotchart(t(caff.marital))
#Tips:图中虚线的颜色可以通过lcolor参数来更改,默认是灰色的。
③ 饼图
> opar<-par(mfrow=c(2,2),mex=0.8,mar=c(1,1,2,1))
> slices=c("white","grey50","grey80","black")
> pie(caff.marital['Married',],main="Married",col=slices)
> pie(caff.marital['Divorced',],main="Divorced",col=slices)
> pie(caff.marital['Single',],main="Single",col=slices)
> par(opar)
#Tips:par是我们之前用来减少子图之间空白的技巧函数。参数col设置饼块的颜色。
对这部分感兴趣的朋友,可以探索不同类型的线和点图的可能性。变化图形的符号、线型、线宽和颜色。> ?par
至此,我们对统计描述的介绍就告一段落了,我们分别介绍了不分组数据的描述、分组数据描述和分类变量描述三种不同情况。在统计描述过后我们就需要做出统计推断了,之后的内容就是关于各种统计检验和模型的介绍,敬请期待。
参考资料:
1. 《R语言统计入门(第二版)》人民邮电出版社 Peter Dalgaard著
2. 《R语言初学者指南》人民邮电出版社 Brian Dennis著
3. Vicky的小笔记本《blooming for you》by Vicky
End