利用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 

相關文章
相關標籤/搜索