用ggplot绘图(三)
2015年04月05日 R 可视化 ggplot 行 添加评论说说geom[etry]
很显然geom_*
中geom就是geometry的缩写,所以geom_*
是用来定义用什么样的几何属性来显示数据的。这基本是大部分图形库对于图像的定义,一来你需要回答的是你要画散点图呢,还是曲线图呢,是多边形呢还是其他的。然后再去看怎么用每个函数。ggplot在这方面使用geom_*
来构建这种映射。
需要注意到的是通常情况下的几何属性其实有两类,这一点在ggplot里得到了区分。一类几何属性仅描述绘制图像的几何内容,比如用点,曲线,多边形等等来显示数据;另外一类是几何性质与统计特性的结合,比如直方图,光滑曲线,回归曲线等等。第一类是单纯的几何形式,用来构造数据和几何属性间的一一映射,第二类则先对数据进行统计分析,然后再和几何属性联系起来。原则上讲,绘图库的几何映射只应该包括第一类函数。这样的设置固然优美和统一,不过现实往往是残酷的,往往为了使用者的少输入字符或者不明真相的用户的方便,绘图库设计者不得不做一些退让。ggplot正是那么做的。在ggplot中,geom_*
同时提供了这两类函数。从文档上可以明显的感觉出设计者在这一方面的退让,对于第二类函数文档会在醒目位置提醒用户这个函数是某个stat_*
函数和某个geom_*
函数的结合。其中,stat_*
函数是用来对数据进行统计变换的。如果用户想对数据的统计变换方式加以控制,你需要到stat_*
函数部分查看选项,因为这个函数实际上是那两个函数的简单叠加。
大部分ggplot的函数意义都是自明的,我觉得给予逐一的解释和范例意义并不大。我们下面展示一下ggplot里面的几个常用geom类型的绘图实例。
散点几何形式:geom_point
顾名思义,这个函数就是一般函数库里的散点图。下面我们用散点图来研究一下mtcars的数据,对于mtcars的数据变量的简单介绍如下:
[, 1] mpg Miles/(US) gallon
[, 2] cyl Number of cylinders
[, 3] disp Displacement (cu.in.)
[, 4] hp Gross horsepower
[, 5] drat Rear axle ratio
[, 6] wt Weight (lb/1000)
[, 7] qsec 1/4 mile time
[, 8] vs V/S
[, 9] am Transmission (0 = automatic, 1 = manual)
[,10] gear Number of forward gears
[,11] carb Number of carburetors
我们可以用以下散点图来研究一下质量和耗油量的关系,同时可以看看不同质量和耗油量的车辆的气缸数量和前置齿轮数量之间的关系。
library(ggplot2)
data(mtcars)
mtcars$cyl <- factor(mtcars$cyl)
p <- ggplot(mtcars,aes(wt, mpg, size=gear, color=cyl))
p + geom_point()
这个图像的信息量很大,看起来也有点复杂,特别是对于第一次接触高维数据分析的人。这个图是一个典型的四维数据分析图,从图中首先可以看到随着质量的增加耗油量在减小,而且关系似乎是线性的。实际上我们可以通过添加回归线来查看这一关系。
p <- ggplot(mtcars,aes(wt, mpg))
p <- p + geom_point(aes(size=gear, color=cyl))
p + geom_smooth(method=lm, fill='lightblue', color='darkblue', size=1)
可以看到数据的线性还是不错的,当然geom_smooth
不止可以线性回归了,下面是用loess
光滑的结果:
p + geom_smooth(method=loess, color='red', fill='green', size=1)
实际上,要完整理解上面两个例子,需要在讨论了层之后,所以关于散点图的内容就先说到这里了。
柱状图:geom_bar
第二个我们要讨论的geom_*
命令是geo_bar
,而不是geom_line
。这是因为geom_line
和geom_point
的区别很小,如果你学会了geom_point
,你也就学会了geom_line
唯一的区别是一个使用散点图来表示,一个是用折线来表示。
geom_bar
的设计是比较奇怪的,我估计主要的考虑是一般使用这个函数是需要绘制一个变量的直方图,所以默认的这个函数会使用stat_bin
作为统计函数,而不是和其他函数统一的stat_identity
。如果你需要直接将数据的值作为bar的高度,那么你需要修改默认的stat
参数为identity
。由于这破坏了ggplot的统一性,我们下面给一个例子:
dummy <- data.frame(x=1:4, y=c(65,23,78,99))
ggplot(dummy, aes(x, y, fill=y)) + geom_bar(stat='identity')
如果需要分析不同的气缸数量的车辆重量的直方图,可以这样来查看:
ggplot(mtcars, aes(wt,fill=cyl)) + geom_bar(binwidth=.345)
ggplot(mtcars, aes(wt,fill=cyl)) + geom_bar(binwidth=.345, pos='dodge')
ggplot(mtcars, aes(wt,fill=cyl)) + geom_bar(binwidth=.345, pos='fill')
上例中后面两图演示了不同的位置放置的直方图,这实际上是通过position_*
的函数实现的。其中,dodge
是将直方图独立开来显示,默认值是stack
,是将同一x值的y值叠加起来。第三个比较特殊,叫做fill
会将每个x值的数据归一化到1,然后计算每种类型的百分比。
到这里你是不是感觉ggplot好复杂啊,而且有些地方好像不对。ggplot怎么知道是要把整个数据当作一个集合,还是按照某个变量分类呢?比如说,上面的线性回归一例,ggplot怎么知道是对所有数据进行回归,还是按照其他规则分别回归呢?比如:
p <- ggplot(mtcars,aes(wt, mpg, size=gear, color=cyl))
p + geom_point() + geom_smooth(method='lm', size=1)
答案是层,所以下一节我们要讨论层的概念。