ggplot2绘图入门

421,246

I. 导论

1 什么是ggplot2

ggplot2是用于绘图的R语言扩展包,其理念根植于《Grammar of Graphics》一书。它将绘图视为一种映射,即从数学空间映射到图形元素空间。例如将不同的数值映射到不同的色彩或透明度。该绘图包的特点在于并不去定义具体的图形(如直方图,散点图),而是定义各种底层组件(如线条、方块)来合成复杂的图形,这使它能以非常简洁的函数构建各类图形,而且默认条件下的绘图品质就能达到出版要求。

2 与lattice包的比较

ggplot2和lattice都属于高级的格点绘图包,初学R语言的朋友可能会在二者选择上有所疑惑。从各自特点上来看,lattice入门较容易,作图速度较快,图形函数种类较多,比如它可以进行三维绘图,而ggplot2就不能。ggplot2需要一段时间的学习,但当你跨过这个门槛之后,就能体会到它的简洁和优雅,而且ggplot2可以通过底层组件构造前所未有的图形,你所受到的限制只是你的想象力。

建议两种绘图包都可以研究一下。如果时间紧张,需要在一两天之内为论文做一张图,那么推荐用lattice,如果时间充裕,推荐学习ggplot2。

3 基本概念

  • 图层(Layer):如果你用过photoshop,那么对于图层一定不会陌生。一个图层好比是一张玻璃纸,包含有各种图形元素,你可以分别建立图层然后叠放在一起,组合成图形的最终效果。图层可以允许用户一步步的构建图形,方便单独对图层进行修改、增加统计量、甚至改动数据。
  • 标度(Scale):标度是一种函数,它控制了数学空间到图形元素空间的映射。一组连续数据可以映射到X轴坐标,也可以映射到一组连续的渐变色彩。一组分类数据可以映射成为不同的形状,也可以映射成为不同的大小。
  • 坐标系统(Coordinate):坐标系统控制了图形的坐标轴并影响所有图形元素,最常用的是直角坐标轴,坐标轴可以进行变换以满足不同的需要,如对数坐标。其它可选的还有极坐标轴。
  • 位面(Facet):很多时候需要将数据按某种方法分组,分别进行绘图。位面就是控制分组绘图的方法和排列形式。

4 一个例子

下面用ggplot2包内带的汽车测试数据(mpg)来举个例子,用到的三个变量分别是发动机容量(displ)、高速公路上的每加仑行驶里数(hwy)、汽缸数目(cyl)。首先加载ggplot2包,然后用ggplot定义第一层即数据来源。其中aes参数非常关键,它将displ映射到X轴,将hwy映射到Y轴,将cyl变为分类数据后映射为不同的颜色。然后使用+号添加了两个新的图层,第二层是加上了散点,第三层是加上了loess平滑曲线。

[code lang="R"]
library(ggplot2)
p <- ggplot(data=mpg,aes(x=displ,y=hwy,colour=factor(cyl)))
p + geom_point() + geom_smooth()
[/code]

ggplot2绘图入门-图片1
上图是对几种不同汽缸的数据分别平滑,如果需要对整体数据进行平滑,可将colour参数设置在散点图层内而非第一层,这样第三层的平滑图形就不会受到colour参数的影响。

[code lang="R"]
p <- ggplot(mpg,aes(x=displ,y=hwy))
p + geom_point(aes(colour=factor(cyl))) + geom_smooth()
[/code]

ggplot2绘图入门-图片2

II. 图层控制与直方图

ggplot2使用图层将各种图形元素逐步添加组合,从而形成最终结果。第一层必须是原始数据层,其中data参数控制数据来源,注意数据形式只能是数据框格式。aes参数控制了对哪些变量进行图形映射,以及映射方式,aes是Aesthetic的缩写。

下面我们来绘制一个直方图作为示例。数据集仍采取mpg,对hwy变量绘制直方图。首先加载了扩展包,然后用ggplot函数建立了第一层,hwy数据映射到X轴上;使用+号增加了第二层,即直方图对象层。此时p被视为一种层对象,使用summary函数可得到关于它的更多信息,print(p)命令即可进行绘图。

library(ggplot2)
[code lang="R"]
p <- ggplot(data = mpg,aes(x = hwy))
p <- p + geom_histogram()
summary(p)
[/code]

 
data: manufacturer, model, displ, year, cyl, trans,
  drv, cty, hwy, fl, class [234x11]
mapping:  x = hwy
faceting: facet_grid(. ~ ., FALSE)
-----------------------------------
geom_histogram:
stat_bin:
position_stack: (width = NULL, height = NULL)

上面的信息告诉我们,p对象含有两层,第一层数据层描述了变量和映射方式,第二层是直方图对象(geom_histogram),geom表示几何对象,它是ggplot中重要的图层控制对象,因为它负责图形渲染的类型。geom_histogram是图形渲染类型的一种,其它类型可参见官网

每个geom对象都需要有数据输入,数据可以从第一层中自动读取,也可以在aes参数中直接设置。而且每个geom还默认搭配某种统计变换(stat),geom_histogram的默认统计变换是stat_bin。它负责对数据进行分组计数。

下面我们尝试两种更为复杂的直方图,首先将数据按照year这个变量划分为两组,用不同的颜色绘制直方图,而且用频率而非计数来刻画Y轴,并添加密度曲线。
[code lang="R"]
p <- ggplot(mpg,aes(hwy))
p + geom_histogram(position = 'identity',
alpha=0.5,
aes(y = ..density..,
fill = factor(year))) +
stat_density(geom = 'line',
position = 'identity',
aes(colour = factor(year)))
[/code]

ggplot2绘图入门-图片3
如果想将两个直方图分开绘制,也可以使用facet_grid参数,结果如下图所示。ggplot2绘图入门-图片4

III. 位置调整与条形图

位置调整(Position adjustments)是针对同一图层内元素的位置进行微调的方法。它包括五种设置,分别是stack、dodge、fill、identity、jitter。

我们用条形图来展示其用法,仍使用mpg数据集,其中用到的变量是class,即生产汽车的类型,以及year生产年份。下面的条形图是将各类型的汽车数量进行汇集,并以年份作为分组变量。我们首先载入扩展包,然后用频数表对数据进行大致的了解,最后绘制了四种条形图。

[code lang="R"]
library(ggplot2)
with(mpg,table(class,year))
p <- ggplot(data=mpg,aes(x=class,fill=factor(year)))
p + geom_bar(position='dodge')
p + geom_bar(position='stack')
p + geom_bar(position='fill')
p + geom_bar(position='identity',alpha=0.3)
[/code]

ggplot2绘图入门-图片5

ggplot2绘图入门-图片6
ggplot2绘图入门-图片7
ggplot2绘图入门-图片8

可以看到dodge方式是将不同年份的数据并列放置;stack方式是将不同年份数据推叠放置,这也是geom_bar的默认处理方式;fill方式和stack类似,但Y轴不再是计数,而是以百分比显示;identity方式是不做任何改变直接显示出来,所以需要设置透明度才能看得清楚。

geom_bar是绘制条状几何对象,所以也可以用不经汇集的原始数据进行绘图。下面我们用2001到2010年间的美国GDP增长率举个例子。
[code lang="R"]
y=c(1.1,1.8,2.5,3.6,3.1,2.7,1.9,-0.1,-3.5,3.0)
x=2001:2010
data=data.frame(x,y)
p=ggplot(data,aes(x,y,fill=y))
p+geom_bar(stat="identity")+
geom_abline(intercept = 0, slope = 0,size=1,colour='gray')+
geom_text(aes(label=y),hjust=0.5, vjust=-0.5 )+
scale_y_continuous(limits=c(-3.8,4.2))+
labs(x='年份', y='GDP增长率%')+
opts(title = "美国GDP增长率")
[/code]

ggplot2绘图入门-图片9

IV. 散点图

1 色彩和形状的控制

数据特征不仅可以用坐标来表示,也可以用不同的色彩或形状来表示。仍以mpg数据集为例,所用到的变量有cty(城市中行驶距离),hwy(高速路行驶距离),displ(排量大小),year(生产年份)

[code lang="R"]
library(ggplot2)
p <- ggplot(mpg, aes(cty, hwy))
p1 <- p + geom_point(aes(colour = factor(year),shape = factor(year), size = displ), alpha = 0.6, position = 'jitter')
print(p1)
[/code]
ggplot2绘图入门-图片10

我们将1999年生产车型用红色圆形表示,2008年用兰色三角形表示,排量用图形的大小表示,并且设置了透明度和jitter以避免样本点之间的重叠。可观察到2008年生产的大排量车型较多,从而油耗较高,单位油耗行驶距离较短。

2 坐标的控制

上图右上角数据点较为稀疏,这种情况下可用对数变换。为了演示ggplot2对图形坐标的控制,我们对X轴和Y轴均进行对数变换,然后对X轴的坐标显示加以限制,只显示X轴数据的均值,以及一倍标准差的坐标。
[code lang="R"]
cty.mean=with(mpg,mean(cty))
cty.sd=with(mpg,sd(cty))
p1 + scale_x_continuous(trans='log',breaks=c(cty.mean-cty.sd,cty.mean,cty.mean+cty.sd), labels=c("high", "mean", "low")) + scale_y_continuous(trans='log')
[/code]
3 文字说明

利用geom_text函数可添加文字说明以增强图形的可读性

[code lang="R"]
p <- ggplot(mtcars, aes(x=wt, y=mpg,colour=factor(cyl),label=rownames(mtcars)))
p + geom_text(hjust=0,vjust=-1,alpha=0.8)+ geom_point(size=3,aes(shape=factor(cyl)))
[/code]

ggplot2绘图入门-图片11

4 矩阵散点图

ggplot2包中也提供了矩阵散点图函数
[code lang="R"]
plotmatrix(USArrests)+geom_smooth()
[/code]

ggplot2绘图入门-图片12

V. 时间序列

ggplot2包也能对时间序列数据绘图,但在处理上需要有些注意的地方。下面我们以上证指数为例进行作图,首先利用quantmod包从yahoo数据源获取从1997年以来的数据,存于变量SSEC中,抽取收盘数字,然后分别提取时间数据和指数数值,绘图结果如下图。

[code lang="R"]
library(quantmod)
library(ggplot2)
getSymbols('^SSEC',src='yahoo',from = '1997-01-01')
close <- (Cl(SSEC))
time <- index(close)
value <- as.vector(close)
p <- ggplot(data.frame(time,value),aes(time,value))
p + geom_line()
[/code]

ggplot2绘图入门-图片13

我们希望能够在图中加入一些其它的说明元素,以丰富视图中所包含的信息。这些信息包括用不同的颜色区块来表示“江核心”和“胡核心”的执政时期,以及对中国证券市场的若干大事件进行标注。最后的代码和结果如下。
[code lang="R"]
yrng <- range(value)
xrng <- range(time)
data <- data.frame(start=as.Date(c('1997-01-01','2003-01-01')),end=as.Date(c('2002-12-30','2012-01-20')),core=c('jiang','hu'))
timepoint <- as.Date(c('1999-07-02','2001-07-26','2005-04-29','2008-01-10','2010-03-31'))
events <- c('证券法实施','国有股减持','股权分置改革','次贷危机爆发','融资融券试点')
data2 <- data.frame(timepoint,events,stock=value[time %in% timepoint])
[/code]

[code lang="R"]
p + geom_line()
+ geom_rect(aes(NULL,NULL,xmin = start, xmax = end, fill = core),ymin = yrng[1],ymax=yrng[2],data = data)
+ scale_fill_manual(values = alpha(c('blue','red'),0.2))
+ geom_text(aes(timepoint, stock, label = events),data = data2,vjust = -2,size = 5)
+ geom_point(aes(timepoint, stock),data = data2,size = 5,colour = alpha('red',0.5))
[/code]
ggplot2绘图入门-图片14
参考资源:

http://xccds1977.blogspot.com

http://had.co.nz/ggplot2/ (官方主站)

ggplot2 Elegant Graphics for Data Analysis (下载

评论  4  访客  2
    • cionysus 0

      感谢分享!

      • zhuwen96485 1

        感谢楼主分享

      发表评论

      匿名网友