一、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