利用ggplot2画出各类漂亮图片详细教程

一、Why use ggplot2

ggplot2是我见过最human friendly的画图软件,这得益于Leland Wilkinson在他的著做《The Grammar of Graphics》中提出了一套图形语法,把图形元素抽象成能够自由组合的成分,Hadley Wickham把这套想法在R中实现。html

为何要学习ggplot2,能够参考ggplot2: 数据分析与图形艺术的序言(btw: 在序言的最后,我被致谢了)。编程

Hadley Wickham也给出一堆理由让咱们说服本身,我想再补充一点,Hadley Wickham是学医出身的,作为学生物出身的人有什么理由不支持呢:)数组

ggplot2基本要素app

  • 数据(Data)和映射(Mapping)
  • 几何对象(Geometric)
  • 标尺(Scale)
  • 统计变换(Statistics)
  • 坐标系统(Coordinante)
  • 图层(Layer)
  • 分面(Facet)
  • 主题(Theme)

这里将从这些基本要素对ggplot2进行介绍。ide

二、数据(Data)和映射(Mapping)

下面以一份钻石的数据为例,这份数据很是大,随机取一个子集来画图。函数

require(ggplot2)
data(diamonds)
set.seed(42)
small <- diamonds[sample(nrow(diamonds), 1000), ]
head(small)
##       carat       cut color clarity depth table price    x    y    z
## 49345  0.71 Very Good     H     SI1  62.5    60  2096 5.68 5.75 3.57
## 50545  0.79   Premium     H     SI1  61.8    59  2275 5.97 5.91 3.67
## 15434  1.03     Ideal     F     SI1  62.4    57  6178 6.48 6.44 4.03
## 44792  0.50     Ideal     E     VS2  62.2    54  1624 5.08 5.11 3.17
## 34614  0.27     Ideal     E     VS1  61.6    56   470 4.14 4.17 2.56
## 27998  0.30   Premium     E     VS2  61.7    58   658 4.32 4.34 2.67
summary(small)
##      carat              cut      color      clarity        depth     
##  Min.   :0.220   Fair     : 28   D:121   SI1    :258   Min.   :55.2  
##  1st Qu.:0.400   Good     : 88   E:186   VS2    :231   1st Qu.:61.0  
##  Median :0.710   Very Good:227   F:164   SI2    :175   Median :61.8  
##  Mean   :0.819   Premium  :257   G:216   VS1    :141   Mean   :61.7  
##  3rd Qu.:1.070   Ideal    :400   H:154   VVS2   : 91   3rd Qu.:62.5  
##  Max.   :2.660                   I:106   VVS1   : 67   Max.   :72.2  
##                                  J: 53   (Other): 37                 
##      table          price             x              y       
##  Min.   :50.1   Min.   :  342   Min.   :3.85   Min.   :3.84  
##  1st Qu.:56.0   1st Qu.:  990   1st Qu.:4.74   1st Qu.:4.76  
##  Median :57.0   Median : 2595   Median :5.75   Median :5.78  
##  Mean   :57.4   Mean   : 4111   Mean   :5.79   Mean   :5.79  
##  3rd Qu.:59.0   3rd Qu.: 5495   3rd Qu.:6.60   3rd Qu.:6.61  
##  Max.   :65.0   Max.   :18795   Max.   :8.83   Max.   :8.87  
##                                                              
##        z       
##  Min.   :2.33  
##  1st Qu.:2.92  
##  Median :3.55  
##  Mean   :3.57  
##  3rd Qu.:4.07  
##  Max.   :5.58  
##

画图其实是把数据中的变量映射到图形属性上。以克拉(carat)数为X轴变量,价格(price)为Y轴变量。工具

p <- ggplot(data = small, mapping = aes(x = carat, y = price))

上面这行代码把数据映射XY坐标轴上,须要告诉ggplot2,这些数据要映射成什么样的几何对象,下面以散点为例:学习

p + geom_point()

几何对象将在下面的小节介绍,这一节,关注的是数据和图形属性之间的映射。字体

若是想将切工(cut)映射到形状属性。只须要:ui

p <- ggplot(data=small, mapping=aes(x=carat, y=price, shape=cut)) 
p+geom_point()

 

再好比我想将钻石的颜色(color)映射颜色属性:

p <- ggplot(data=small, mapping=aes(x=carat, y=price, shape=cut, colour=color))
p+geom_point()
 
 

 

三、几何对象(Geometric)

在上面的例子中,各类属性映射由ggplot函数执行,只须要加一个图层,使用geom_point()告诉ggplot要画散点,因而全部的属性都映射到散点上。

geom_point()完成的就是几何对象的映射,ggplot2提供了各类几何对象映射,如geom_histogram用于直方图,geom_bar用于画柱状图,geom_boxplot用于画箱式图等等。

不一样的几何对象,要求的属性会有些不一样,这些属性也能够在几何对象映射时提供,好比上一图,也能够用如下语法来画:

p <- ggplot(small) 
p+geom_point(aes(x=carat, y=price, shape=cut, colour=color))

ggplot2支持图层,我一般把不一样的图层中共用的映射提供给ggplot函数,而某一几何对象才须要的映射参数提供给geom_xxx函数。

这一小节咱们来看一下各类经常使用的几何对象。

直方图

直方图最容易,提供一个x变量,画出数据的分布。

ggplot(small)+geom_histogram(aes(x=price))

 

一样能够根据另外的变量给它填充颜色,好比按不一样的切工:

ggplot(small)+geom_histogram(aes(x=price, fill=cut))

 

也能够将其分开,side-by-side地画直方图。

ggplot(small)+geom_histogram(aes(x=price, fill=cut), position="dodge")

还可使用position="fill",按照相对比例来画。

ggplot(small)+geom_histogram(aes(x=price, fill=cut), position="fill")

 

柱状图

柱状图很是适合于画分类变量。在这里以透明度(clarity)变量为例。按照不一样透明度的钻石的数目画柱状图。

ggplot(small)+geom_bar(aes(x=clarity))

 

柱状图两个要素,一个是分类变量,一个是数目,也就是柱子的高度。数目在这里不用提供,由于ggplot2会经过x变量计算各个分类的数目。

固然你想提供也是能够的,经过stat参数,可让geom_bar按指定高度画图,好比如下代码:

ggplot()+geom_bar(aes(x=c(LETTERS[1:3]),y=1:3), stat="identity")

 

柱状图和直方图是很像的,直方图把连续型的数据按照一个个等长的分区(bin)来切分,而后计数,画柱状图。而柱状图是分类数据,按类别计数。咱们能够用前面直方图的参数来画side-by-side的柱状图,填充颜色或者按比例画图,它们是高度一致的。

柱状图是用来表示计数数据的,但在生物界却被常常拿来表示均值,加上偏差来表示数据分布,这能够一般图层来实现,我将在图层一节中给出实例。

密度函数图

说到直方图,就不得不说密度函数图,数据和映射和直方图是同样的,惟一不一样的是几何对象,geom_histogram告诉ggplot要画直方图,而geom_density则说咱们要画密度函数图,在咱们熟悉前面语法的状况下,很容易画出:

ggplot(small)+geom_density(aes(x=price, colour=cut))

 

 

ggplot(small)+geom_density(aes(x=price,fill=clarity))

 

 

colour参数指定的是曲线的颜色,而fill是往曲线下面填充颜色。

箱式图

数据量比较大的时候,用直方图和密度函数图是表示数据分布的好方法,而在数据量较少的时候,好比不少的生物实验,不少时候你们都是使用柱状图+errorbar的形式来表示,不过这种方法的信息量很是低,被Nature Methods吐槽,这种状况推荐使用boxplot。

 

 

ggplot(small)+geom_boxplot(aes(x=cut, y=price,fill=color))

geom_boxplot将数据映射到箱式图上,上面的代码,咱们应该很熟悉了,按切工(cut)分类,对价格(price)变量画箱式图,再分开按照color变量填充颜色。

 

ggplot2提供了不少的geom_xxx函数,能够知足咱们对各类图形绘制的需求。

geom_abline 	geom_area 	
geom_bar 		geom_bin2d
geom_blank 		geom_boxplot 	
geom_contour 	geom_crossbar
geom_density 	geom_density2d 	
geom_dotplot 	geom_errorbar
geom_errorbarh 	geom_freqpoly 	
geom_hex 		geom_histogram
geom_hline 		geom_jitter 	
geom_line 		geom_linerange
geom_map 		geom_path 	
geom_point 		geom_pointrange
geom_polygon 	geom_quantile 	
geom_raster 	geom_rect
geom_ribbon 	geom_rug 	
geom_segment 	geom_smooth
geom_step 		geom_text 	
geom_tile 		geom_violin
geom_vline

四、标尺(Scale)

前面咱们已经看到了,画图就是在作映射,不论是映射到不一样的几何对象上,仍是映射各类图形属性。这一小节介绍标尺,在对图形属性进行映射以后,使用标尺能够控制这些属性的显示方式,好比坐标刻度,可能经过标尺,将坐标进行对数变换;好比颜色属性,也能够经过标尺,进行改变。

ggplot(small)+geom_point(aes(x=carat, y=price, shape=cut, colour=color))+scale_y_log10()+scale_colour_manual(values=rainbow(7))

 

以数据(Data)和映射(Mapping)一节中所画散点图为例,将Y轴坐标进行log10变换,再本身定义颜色为彩虹色。

五、统计变换(Statistics)

统计变换对原始数据进行某种计算,而后在图上表示出来,例如对散点图上加一条回归线。

ggplot(small, aes(x=carat, y=price))+geom_point()+scale_y_log10()+stat_smooth()

 

这里就不按颜色、切工来分了,否则ggplot会按不一样的分类变量分别作回归,图就很乱,若是咱们须要这样作,咱们可使用分面,这个将在后面介绍。

这里,aes所提供的参数,就经过ggplot提供,而不是提供给geom_point,由于ggplot里的参数,至关于全局变量,geom_point()和stat_smooth()都知道x,y的映射,若是只提供给geom_point(),则至关因而局部变量,geom_point知道这种映射,而stat_smooth不知道,固然你再给stat_smooth也提供x,y的映射,不过共用的映射,仍是提供给ggplot好。
ggplot2提供了多种统计变换方式:

stat_abline       stat_contour      stat_identity     stat_summary
stat_bin          stat_density      stat_qq           stat_summary2d
stat_bin2d        stat_density2d    stat_quantile     stat_summary_hex
stat_bindot       stat_ecdf         stat_smooth       stat_unique
stat_binhex       stat_function     stat_spoke        stat_vline
stat_boxplot      stat_hline        stat_sum          stat_ydensity

统计变换是很是重要的功能,咱们能够本身写函数,基于原始数据作某种计算,并在图上表现出来,也能够经过它改变geom_xxx函数画图的默认统计参数。
好比我在Proteomic investigation of the interactome of FMNL1 in hematopoietic cells unveils a role in calcium-dependent membrane plasticity的图一中,就把boxplot的中位线替换成了平均值来做图。

六、坐标系统(Coordinante)

坐标系统控制坐标轴,能够进行变换,例如XY轴翻转,笛卡尔坐标和极坐标转换,以知足咱们的各类需求。

坐标轴翻转由coord_flip()实现

ggplot(small)+geom_bar(aes(x=cut, fill=cut))+coord_flip()

 

而转换成极坐标能够由coord_polar()实现:

ggplot(small)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar(theta="y")

 

这也是为何以前介绍经常使用图形画法时没有说起饼图的缘由,饼图实际上就是柱状图,只不过是使用极坐标而已,柱状图的高度,对应于饼图的弧度,饼图并不推荐,由于人类的眼睛比较弧度的能力比不上比较高度(柱状图)

还能够画靶心图:

ggplot(small)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar()

 

以及风玫瑰图(windrose)

ggplot(small)+geom_bar(aes(x=clarity, fill=cut))+coord_polar()

 

七、图层(Layer)

photoshop流行的缘由在于PS 3.0时引入图层的概念,ggplot的牛B之处在于使用+号来叠加图层,这堪称是泛型编程的典范。
在前面散点图上,咱们已经见识过,加上了一个回归线拟合的图层。

有了图层的概念,使用ggplot画起图来,就更加驾轻就熟。

作为图层的一个很好的例子是蝙蝠侠logo,batman logo由6个函数组成,在下面的例子中,我先画第一个函数,以后再加一个图层画第二个函数,不断重复这一过程,直到六个函数所有画好。

require(ggplot2)
f1data.frame(x=x,y=y)
	d -3*sqrt(33)/7,]
	return(d)
}
 
x1data.frame(x2=x2, y2=y2)
p2data.frame(x3=x3, y3=y3)
p3data.frame(x4=x4,y4=y4)
p4data.frame(x5=x5,y5=y5)
p5data.frame(x6=x6,y6=y6)
p6

 

下面再以生物界中经常使用的柱状图+偏差图为实例,展现ggplot2很是灵活的图层。以我2011年发表的文章Phosphoproteome profile of human lung cancer cell line A549中的westernblot数据为例。

Normaldata.frame(V=c("Normal", "Cancer"), mean=m, sd=s)
d$V

八、分面(Facet)

分面可让咱们按照某种给定的条件,对数据进行分组,而后分别画图。

在统计变换一节中,提到若是按切工分组做回归线,显然图会很乱,有了分面功能,咱们能够分别做图。

ggplot(small, aes(x=carat, y=price))+geom_point(aes(colour=cut))+scale_y_log10() +facet_wrap(~cut)+stat_smooth()

 

九、主题(Theme)

经过ggplot画图以后,咱们可能还须要对图进行定制,像title, xlab, ylab这些高频须要用到的,自不用说,ggplot2提供了ggtitle(), xlab()和ylab()来实现。

好比:

p

 


可是这个远远知足不了需求,咱们须要改变字体,字体大小,坐标轴,背景等各类元素,这须要经过theme()函数来完成。

ggplot2提供一些已经写好的主题,好比theme_grey()为默认主题,我常常用的theme_bw()为白色背景的主题,还有theme_classic()主题,和R的基础画图函数较像。

别外ggthemes包提供了一些主题可供使用,包括:

theme_economist theme_economist_white
theme_wsj 	 	theme_excel
theme_few 	 	theme_foundation
theme_igray 	theme_solarized
theme_stata 	theme_tufte
require(ggthemes)
p + theme_wsj()

 

在2013年发表的文章Putative cobalt- and nickel-binding proteins and motifs in Streptococcus pneumoniae中的图3就是使用theme_stata来画的。

至于如何改变这些元素,我以为我以前画囧字的博文能够作为例子:

fdata.frame(x=x,y=y)
 
p

 

详细的说明,能够参考?theme的帮助文档。

十、二维密度图

在这个文档里,为了做图方便,咱们使用diamonds数据集的一个子集,若是使用全集,数据量太大,画出来散点就糊了,这种状况可使用二维密度力来呈现。

ggplot(diamonds, aes(carat, price))+ stat_density2d(aes(fill = ..level..), geom="polygon")+ scale_fill_continuous(high="darkred",low="darkgreen")

 

十一、ggplot2实战

果壳知性里有帖子介绍了个猥琐邪恶的曲线,引来无数宅男用各类工具来画图,甚至于3D动态图都出来了。这里用ggplot2来画。3D版本请猛击此处。

fdata.frame(x=c(x1,x2,x3), y=rep(y,3), type=rep(LETTERS[1:3], each=length(y)))
p

再来一个蝴蝶图,详见《Modern Applied Statistics with S-PLUS》第一章。

theta data.frame(x=radius*sin(theta), y=radius*cos(theta))
ggplot(dd, aes(x, y))+geom_path()+theme_null()+xlab("")+ylab("")

 

文章转自: http://www.360doc.com/content/16/0630/23/3852985_572053234.shtml 

相关文章
相关标签/搜索