3.3 高级绘图函数
大部分高级绘图函数均有add参数(plot函数没有)。如果add=FALSE(默认),则在新窗口中创建一个图形;如果add=TRUE,则在当前活动窗口中的原有图形之上叠加图形。在基础包中,R提供了绘制常见图形的功能,包括散点图、气泡图、柱状图、饼图、线图,也提供了一些专业的统计图形,如茎叶图、Q-Q图等。表3-9列出了基础包中可以绘制的一些图形。
3.3.1 散点图
1.散点图
R中创建散点图的基础函数是plot(x,y),其中x和y是数值型向量,代表图形中的(x,y)点。如果样本变量只有一个,则需要把x参数设置为样本数据。
下面通过两个小例子来演示。执行以下代码得到的结果如图3-17所示。
> par(mfrow=c(1,2))
> # 绘制一维数据
> plot(x=rnorm(10))
> # 绘制二维数据
> plot(women)
> par(mfrow=c(1,1))
因为左图绘制的是一维数据,所以将数据赋予x参数;右图是二维数据,R将women数据框的第一列变量(height)赋予x参数,第二列变量(weight)赋予y参数,并将变量名作为坐标轴标签。
2.散点图矩阵
散点图矩阵是散点图的高维扩展,它从一定程度上克服了在平面上展示高维数据的困难,在展示多维数据的两两关系时有着不可替代的作用。R中有多种绘制散点图矩阵的函数。plot函数可以绘制散点图矩阵,此外基础包还有专门绘制散点图矩阵的pairs函数。
当把超过两列的数据框赋予plot函数时,就可以绘制散点图矩阵。以鸢尾花数据集的前四列为例进行演示。执行以下代码,得到的图形如图3-18所示。
> # 绘制散点图矩阵
> plot(iris[,1:4],main="利用plot函数绘制散点图矩阵")
从散点图矩阵可以看出,变量Petal.Length与变量Petal.Width有很强的正相关性。
也可以利用pairs函数实现图3-18的效果。代码如下。
> # 方法一
> pairs(iris[,1:4],main="利用pairs函数绘制散点图矩阵")
> # 方法二
> pairs(~Sepal.Length+Sepal.Width+Petal.Length+Petal.Width,
+ data=iris,main="利用pairs函数绘制散点图矩阵")
3.3.2 气泡图
散点图一般只能较好地展示二维数据,气泡图则是在其基础上另外通过散点的大小来表达第三维变量的数值。同样,也可以使用plot函数绘制气泡图,通过将第三个变量赋予参数cex来控制气泡的大小。
从ggplot2包中的钻石数据集diamonds中随机抽取500个样本,绘制简单气泡图进行演示。执行以下代码得到的结果如图3-19所示。
> data("diamonds",package = "ggplot2")
> # 随机抽取500个样本
> diamonds1 <- diamonds[sample(1:nrow(diamonds),500),]
> attach(diamonds1)
> # 计算钻石体积
> volumn <- x*y*z
> # 把钻石体积进行归一化处理,并赋予对象size
> size <- (volumn-min(volumn))/(max(volumn)-min(volumn))
> # 绘制气泡图
> plot(carat,price,cex=size*2)
也可以用symbols函数来创建气泡图。该函数可以在指定的(x,y)坐标上绘制圆圈图、方形图、星形图、温度计图和箱线图。以绘制圆圈图为例:symbols(x,y,circle=r),其中x、y和circle参数是需要设置的向量,分别表示x轴、y轴和圆圈半径。
现在通过一个小例子来演示。执行以下代码得到的结果如图3-20所示。
> x<-rnorm(10)
> y<-rnorm(10)
> r<-abs(rnorm(10))
> symbols(x,y,circle = r,
+ bg=rainbow(10))
3.3.3 线图
设置plot函数的type参数,将散点图上的点从左往右连接起来,就会得到一个线图。在绘制线图时,type参数可以设置的值如表3-10所示。
执行以下代码,查看不同类型线图的效果。结果如图3-21所示。
3.3.4 柱状图
在R中用barplot函数可以绘制柱状图和条形图。barplot函数的主要参数如表3-11所示。
对1940年弗吉尼亚州的死亡率的数据VADeaths绘制柱状图和条形图,通过参数horiz来控制。执行如下代码得到的结果如图3-22所示。
> par(mfrow=c(1,2))
> for(i in c(FALSE,TRUE)){
+ barplot(VADeaths,horiz = i,beside = T,col = rainbow(5))
+ }
> par(mfrow=c(1,1))
由于多个柱子水平并列展示,所以需要添加图例方便解读数据。可以设置legend.text参数来实现。执行以下代码得到的结果如图3-23所示。
> barplot(VADeaths,beside = T,col = rainbow(5),
+ legend.text = rownames(VADeaths))
3.3.5 饼图
饼图为一个由许多扇形组成的圆,各个扇形的大小比例等于变量各水平的频数比例。饼图比条形图简单,描述比例较直观。其基本形式为:
pie(x,labels=names(x),…)
其中x为画图的非负数值向量,label为生成标签表达式。
如果想查看mtcars数据集中cyl不同数值的占比。执行以下代码得到的结果如图3-24所示。
> pie(table(mtcars$cyl))
3.3.6 直方图和密度图
直方图是定量变量常用的图表之一。其做法是,把横坐标分成若干通常是等宽度的区间,然后计算数据在各个区间上的频数,并在各区间上画出高度与数据在相应区间的频数成比例的矩形条。纵坐标当然也可能是比例而不一定是频数,但这并不改变图的形状,只是纵坐标单位的不同。可以使用hist()函数创建直方图。
hist函数的基本形式为his(x,…),hist函数的主要参数如表3-12所示。
下面举例说明如何利用hist()绘制直方图。
对ggplot2包自带的美国经济数据economics的个人储蓄率和一周内平均失业持续时间绘制直方图。对psavert和uempmed分别绘制了两个图,一个有较少的区间,一个有较多的区间,可以很清楚地看出区间划分对直方图的影响。执行以下代码得到的结果如图3-25所示。
> data(economics, package = "ggplot2")
> attach(economics) #将economics加载到内存
> par(mfrow=c(2,2))
> hist(psavert,8,xlab="个人储蓄率",ylab="频数",col="blue",
+ main="个人储蓄率直方图(较少区间)")
> hist(psavert,30,xlab="个人储蓄率",ylab="频数",col="blue",
+ main="个人储蓄率直方图(较多区间)")
> hist(uempmed,8,xlab="一周内平均失业持续时间",ylab="频数",col="green",
+ main="一周内平均失业持续时间(较少区间)")
> hist(uempmed,30,xlab="一周内平均失业持续时间",ylab="频数",col="green",
+ main="一周内平均失业持续时间(较多区间)")
> par(mfrow=c(1,1))
> detach(economics) #将economics从内存中释放
有一种与直方图有密切关系的图,即密度图。很多统计学家都建议用密度图代替直方图,因为密度图更容易解读。首先要用density函数计算核密度估计量,然后用plot函数画出估计量。其基本形式为plot(density(x))。
核密度图经常会加上rug。rug是用于绘制坐标轴密度线的函数,实际上就是在坐标轴上添加一条图形,用短线段表示一个点。
继续以economics为例,绘制个人储蓄率的核密度图,并添加轴须图。执行以下代码得到的结果如图3-26所示。
> plot(density(economics$psavert))
> rug(economics$psavert)
3.3.7 Q-Q图
Q-Q(Quantile-Quantile)图会将样本数据的分布与理论分布(通常是正态分布)做比较,即Q-Q图会画出样本的分位数和理论分布的分位数。如果样本数据的分布和理论分布一致,那么所有的点都会在从左下角到右上角的45°对角线上。Q-Q图可以有效地判断实际分布和期望分布的差异。在R中可以用qqnorm函数绘制Q-Q图。
继续以economics为例,绘制个人储蓄率的Q-Q图。执行以下代码得到的结果如图3-27所示。
> qqnorm(economics$psavert)
3.3.8 箱线图
箱线图(又称盒形图)通过绘制连续变量的最小值、下四分位数Q1(第25百分位数)、中位数(第50百分位数)、上四分位数Q3(第75百分位数)以及最大值,描述连续型变量的分布。它是由一个盒子(box)和两边各一条线(whisker)组成。如果箱线图是竖直的,那么盒子上下边分别代表Q1和Q3,显然,有约一半的中间大小的数据值落在盒子的范围内。在盒子中间有一条线,这是中位数,盒子的长度等于上下四分位数之差,称为四分位间距或四分位极差(IQR)。在1.5倍IQR范围外的点,箱线图都识别为异常值,故箱线图也是异常值甄别常用的手段之一。在R基础包中用boxplot函数可以绘制箱线图。
以鸢尾花数据集iris为例,绘制花萼长度按照物种分类的箱线图。执行以下代码得到的结果如图3-28所示。
> boxplot(iris$Sepal.Length~iris$Species,col=rainbow(3))
可见,种类setosa的数据整体明显低于其他两个种类,且种类virginica有一个异常点,故箱线图也是用来识别一组数据是否有异常点的常用方法之一。
3.3.9 茎叶图
茎叶图(stem-and-leaf plot)在数据量不大的情况下,既显示了完整的原始数据,又显示了数据分布的状态,它像一片带有长短不一的叶子的茎。在R中用stem函数绘制茎叶图。
以汽车数据集mtcars数据的汽车重量wt为例进行说明。执行以下代码。
> stem(mtcars$wt)
The decimal point is at the |
1 | 5689
2 | 123
2 | 56889
3 | 22224444
3 | 55667888
4 | 1
4 |
5 | 334
结果中的第一行1 | 5689表示wt数据有1.5、1.6、1.8、1.9,其他行以相同方式解读。
3.3.10 点图
点图提供了一种在简单水平刻度上绘制大量有标签值的方法,可以用dotchart函数创建点图。其基本格式为:dotchart(x,labels=)。其中x是一个数值向量,labels是由每个点的标签组成的向量。
继续以汽车数据集mtcars的每加仑英里数mpg数据为例进行说明。执行以下代码得到的结果如图3-29所示。
> dotchart(mtcars$mpg,labels = rownames(mtcars))
3.3.11 马赛克图
马赛克图常用于描绘列联表那样的数据。R基础包中的mosaicplot()函数可以绘制马赛克图。
以Titanic数据集为例,它包含了存活或者死亡的乘客数,乘客的船舱等级、性别以及年龄层。执行以下代码,查看分类细节。
> ftable(Titanic)
Survived No Yes
Class Sex Age
1st Male Child 0 5
Adult 118 57
Female Child 0 1
Adult 4 140
2nd Male Child 0 11
Adult 154 14
Female Child 0 13
Adult 13 80
3rd Male Child 35 13
Adult 387 75
Female Child 17 14
Adult 89 76
Crew Male Child 0 0
Adult 670 192
Female Child 0 0
Adult 3 20
执行以下代码绘制马赛克图,结果如图3-30所示。
> mosaicplot(Titanic)
从上面的马赛克图可以看出,大部分孩子都处在二等舱和三等舱;在头等舱的大部分女性都存活下来,而三等舱中仅有一半女性存活。
除了基础包中的mosaiplot函数可以绘制马赛克图外,vcd包中的mosaic( )函数也可以绘制马赛克图,它具有更多扩展功能。
同样以Titanic数据集为例,执行以下代码得到的马赛克图如图3-31所示。
> library(vcd)
载入需要的程辑包:grid
> mosaic(Titanic,shade = T,legend = T)
扩展的马赛克图添加了颜色和阴影面积来表示拟合模型的残差值。蓝色阴影表明,在假定生存率和船舱等级、性别和年龄段无关的条件下,该类别的生存率通常超过预期值。