學(xué)習(xí)資料:https://mp.weixin.qq.com/s/r6pfSU-88e86cUjxp3yFnQ 網(wǎng)紅教授Y書原創(chuàng)公眾號教程ggplot2專題
一、理解數(shù)據(jù)和映射
下面以內(nèi)置數(shù)據(jù)集鉆石的數(shù)據(jù)為例,這份數(shù)據(jù)總共有53940行10列,隨機取一個子集來畫圖。
rm(list = ls())
library(ggplot2)
data(diamonds)
dim(diamonds)
set.seed(100)
dat <- diamonds[sample(nrow(diamonds), 1000), ]
head(dat)
查看隨機取的子集前幾行
> dim(diamonds)
[1] 53940 10
> head(dat)
# A tibble: 6 x 10
carat cut color clarity depth table price x y z
<dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
1 1.26 Ideal G SI1 59.6 57 6738 7.08 7.04 4.21
2 0.7 Ideal D VS2 62.7 57 3448 5.65 5.67 3.55
3 0.36 Ideal F SI1 62 56 770 4.59 4.54 2.83
4 2.1 Premium J SI2 59.1 58 12494 8.46 8.4 4.98
5 1.21 Premium D SI2 59.7 58 4946 7.06 6.96 4.19
6 2 Good E SI2 64.7 57 15393 7.75 7.86 5.05
以克拉數(shù)為X軸變量,價格為Y軸變量。
p <- ggplot(data = dat, mapping = aes(x = carat, y = price))
p + geom_point()

如果想將切工(cut)映射到形狀屬性。在aes中添加參數(shù):
p <- ggplot(data=dat, mapping=aes(x=carat, y=price, shape=cut))
p+geom_point()

再加一個參數(shù)添加顏色:
p <- ggplot(data=dat, mapping=aes(x=carat, y=price, shape=cut, colour=color))
p+geom_point()

二、理解幾何對象(Geometric)
在上面的例子中,各種屬性映射由ggplot函數(shù)執(zhí)行,只需要加一個圖層,使用geom_point()告訴ggplot要畫散點,于是所有的屬性都映射到散點上。
geom_point()完成的就是幾何對象的映射,ggplot2提供了各種幾何對象映射,如geom_histogram用于直方圖,geom_bar用于畫柱狀圖,geom_boxplot用于畫箱線圖等等。ggplot2提供了很多的geom_xxx函數(shù)來完成相應(yīng)的幾何映射,可以滿足我們對各種圖形繪制的需求。
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
不同的幾何對象,要求的屬性會有些不同,這些屬性也可以在幾何對象映射時提供,比如上一圖,也可以用以下語法來畫:
p <- ggplot(dat)
p+geom_point(aes(x=carat, y=price, shape=cut, colour=color))
下面就是幾個常見的幾何映射示例:
直方圖
直方圖最容易,提供一個x變量,畫出數(shù)據(jù)的分布。
ggplot(dat)+geom_histogram(aes(x=price, fill=cut))

展示效果不太好,也可以將其分開,side-by-side地畫直方圖。
ggplot(dat)+geom_histogram(aes(x=price, fill=cut), position="dodge")

還可以使用position=”fill”,按照相對比例來畫。就是常見的堆積柱狀圖
ggplot(dat)+geom_histogram(aes(x=price, fill=cut), position="fill")

柱狀圖非常適合于畫分類變量。
柱狀圖是用來表示計數(shù)數(shù)據(jù)的,但在生物界卻被經(jīng)常拿來表示均值,加上誤差來表示數(shù)據(jù)分布,這可以通常圖層來實現(xiàn),我將在圖層一節(jié)中給出實例。
密度函數(shù)圖
密度函數(shù)圖,數(shù)據(jù)和映射和直方圖是一樣的,唯一不同的是幾何對象函數(shù),geom_histogram告訴ggplot要畫直方圖,而geom_density則是畫密度函數(shù)圖,直接套用即可:
ggplot(dat)+geom_density(aes(x=price, colour=cut))

改變一個參數(shù)
ggplot(dat)+geom_density(aes(x=price,fill=clarity))
結(jié)果如下:

colour參數(shù)指定的是曲線的顏色,而fill是往曲線下面填充顏色。
箱式圖
數(shù)據(jù)量比較大的時候,用直方圖和密度函數(shù)圖是表示數(shù)據(jù)分布的好方法,而在數(shù)據(jù)量較少的時候,比如很多的生物實驗,很多時候大家都是使用柱狀圖+errorbar的形式來表示,不過這種方法的信息量非常低,被Nature Methods吐槽,這種情況推薦使用boxplot(箱式圖或箱線圖)。
ggplot(dat)+geom_boxplot(aes(x=cut, y=price,fill=color))

更換幾何對象映射函數(shù)geom_boxplot將數(shù)據(jù)映射到箱式圖上,按切工(cut)分類,對價格(price)變量畫箱式圖,再分開按照color變量填充顏色。
三、修改標(biāo)尺
分類屬性映射標(biāo)尺修改
在對圖形屬性進行映射之后,使用標(biāo)尺可以控制這些屬性的顯示方式,比如坐標(biāo)刻度,可能通過標(biāo)尺,將坐標(biāo)進行對數(shù)變換;比如顏色屬性,也可以通過標(biāo)尺,進行改變。
ggplot(dat)+geom_point(aes(x=carat, y=price, shape=cut, colour=color))+
scale_y_log10()+
scale_colour_manual(values=rainbow(7))
結(jié)果如下:

以第一部分數(shù)據(jù)和映射示例中所畫散點圖為例,將Y軸坐標(biāo)進行l(wèi)og10變換,再自己定義顏色為彩虹色。
統(tǒng)計變換(Statistics)標(biāo)尺修改
統(tǒng)計變換對原始數(shù)據(jù)進行某種計算,然后在圖上表示出來,例如對散點圖上加一條回歸線。
ggplot(dat, aes(x=carat, y=price))+
geom_point()+
scale_y_log10()+
stat_smooth()

注意:
- 這里就不按顏色、切工來分了,不然ggplot會按不同的分類變量分別做回歸,圖就很亂,如果我們需要這樣做,我們可以使用分面。
- 這里,aes所提供的參數(shù),就通過ggplot提供,而不是提供給geom_point,因為ggplot里的參數(shù),相當(dāng)于全局變量,geom_point()和stat_smooth()都知道x,y的映射,如果只提供給geom_point(),則相當(dāng)于是局部變量,geom_point知道這種映射,而stat_smooth不知道,當(dāng)然你再給stat_smooth也提供x,y的映射,不過共用的映射,還是提供給ggplot更好。
ggplot2提供了多種統(tǒng)計變換方式:
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
統(tǒng)計變換是非常重要的功能,我們可以自己寫函數(shù),基于原始數(shù)據(jù)做某種計算,并在圖上表現(xiàn)出來,也可以通過它改變geom_xxx函數(shù)畫圖的默認統(tǒng)計參數(shù)。
四、坐標(biāo)系統(tǒng)(Coordinante)
坐標(biāo)系統(tǒng)控制坐標(biāo)軸,可以進行變換,例如XY軸翻轉(zhuǎn),笛卡爾坐標(biāo)和極坐標(biāo)轉(zhuǎn)換,以滿足我們的各種需求。
坐標(biāo)軸翻轉(zhuǎn)由coord_flip()函數(shù)實現(xiàn)
ggplot(dat)+geom_bar(aes(x=cut, fill=cut))+coord_flip()

而轉(zhuǎn)換成極坐標(biāo)可以由
coord_polar()函數(shù)映射實現(xiàn):
ggplot(dat)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar(theta="y")

這也是為什么之前介紹常用圖形畫法時沒有提及餅圖的原因,餅圖實際上就是柱狀圖,只不過是使用極坐標(biāo)而已,柱狀圖的高度,對應(yīng)于餅圖的弧度,餅圖并不推薦,因為人類的眼睛比較弧度的能力比不上比較高度(柱狀圖)。
還可以畫靶心圖:
ggplot(dat)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar()

風(fēng)玫瑰圖(windrose)
ggplot(dat)+geom_bar(aes(x=clarity, fill=cut))+coord_polar()

五、圖層
圖層概念在上面的散點圖加回歸曲線已經(jīng)展示過了,還可以展示更復(fù)雜的,這就是ggplot2的優(yōu)秀之處了,Y叔舉了個蝙蝠圖的例子我就不重復(fù)了。
六、分面(Facet)
在《ggplot2: 數(shù)據(jù)分析與圖形藝術(shù)》一書的翻譯中,一開始譯者把facet翻譯成切片,Y叔推薦翻譯成分面,分面可以讓我們按照某種給定的條件,對數(shù)據(jù)進行分組,然后分別畫圖。
在統(tǒng)計變換一節(jié)中,提到如果按切工分組作回歸線,顯然圖會很亂,有了分面功能,我們可以分別作圖。
ggplot(dat, 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()來實現(xiàn)。 比如:
p <- ggplot(dat)+geom_boxplot(aes(x=cut, y=price,fill=color))
p + ggtitle("Price vs Cut")+xlab("Cut")+ylab("Price")

但是這個遠遠滿足不了需求,我們需要改變字體,字體大小,坐標(biāo)軸,背景等各種元素,這需要通過
theme()函數(shù)來完成。
ggplot2提供一些已經(jīng)寫好的主題,比如theme_grey()為默認主題,我經(jīng)常用的theme_bw()為白色背景的主題,還有theme_classic()主題,和R的基礎(chǔ)畫圖函數(shù)較像。
別外ggthemes包提供了一些主題可供使用,包括:
theme_economist theme_economist_white
theme_wsj theme_excel
theme_few theme_foundation
theme_igray theme_solarized
theme_stata theme_tufte
library(ggthemes)
p + theme_wsj()

二維密度圖
在這個文檔里,為了作圖方便,我們使用diamonds數(shù)據(jù)集的一個子集,如果使用全集,數(shù)據(jù)量太大,畫出來散點就糊了,這種情況可以使用二維密度力來呈現(xiàn)。
ggplot(dat, aes(carat, price))+
stat_density2d(aes(fill = ..level..), geom="polygon")+
scale_fill_continuous(high='darkred',low='darkgreen')

數(shù)據(jù)太多就容易糊。
ggplot2實例
Y叔列了蝴蝶圖,囧字圖等好玩搞怪的圖,最后以生物界中常用的柱狀圖+誤差圖為實例,展示了ggplot2非常靈活的圖層。以他2011年發(fā)表的文章Phosphoproteome profile of human lung cancer cell line A549中的westernblot數(shù)據(jù)為例。這個實例展示了圖層,標(biāo)尺,主題,注釋和各種細節(jié)微調(diào)多種元素。
收藏一下:
Normal <- c(0.83, 0.79, 0.99, 0.69)
Cancer <- c(0.56, 0.56, 0.64, 0.52)
m <- c(mean(Normal), mean(Cancer))
s <- c(sd(Normal), sd(Cancer))
d <- data.frame(V=c("Normal", "Cancer"), mean=m, sd=s)
d$V <- factor(d$V, levels=c("Normal", "Cancer"))
p <- ggplot(d, aes(V, mean, fill=V, width=.5))
p <- p+geom_errorbar(aes(ymin=mean, ymax=mean+sd, width=.2),
position=position_dodge(width=.8))
p <- p + geom_bar(stat="identity", position=position_dodge(width=.8), colour="black")
p <- p + scale_fill_manual(values=c("grey80", "white"))
p <- p + theme_bw() +theme(legend.position="none") + xlab("") + ylab("")
p <- p + theme(axis.text.x = element_text(face="bold", size=12),
axis.text.y = element_text(face="bold", size=12))
p <- p+scale_y_continuous(expand=c(0,0), limits=c(0, 1.2), breaks=seq(0, 1.2, by=.2))
p <- p+geom_segment(aes(x=1, y=.98, xend=1, yend=1.1))
p <- p+geom_segment(aes(x=2, y=.65, xend=2, yend=1.1))
p <- p+geom_segment(aes(x=1, y=1.1, xend=2, yend=1.1))
p <- p + annotate("text", x=1.5, y=1.08, label="*")
print(p)

在這個專題中還有2個神器:
- 《不需要花時間去學(xué)ggplot2主題系統(tǒng)》 中講到的一個RStudio插件,只需要使用以下指令安裝R包:
install.packages("ggThemeAssist")
然后愉快的用鼠標(biāo)點點點就能完成細節(jié)了。
ggplot2不單單能出更多更好看的圖,而且出圖并不比GraphPad Prism困難,除了有調(diào)整細節(jié)的插件,還有點點鼠標(biāo)就可以畫圖的插件- esquisse。
你可以使用下面的指令安裝:
devtools::install_github("dreamRs/esquisse")
然后就可以在RStudio中通過點鼠標(biāo),愉快地用ggplot2畫圖了
esquisse::esquisser()
具體使用方法可以點上面的鏈接看Y叔編輯的動圖,也可以參考簡書作者的教程:http://www.itdecent.cn/p/ecfa0d640250
探索數(shù)據(jù)的時候可以用,而且還可以導(dǎo)出畫圖代碼,簡直不要太優(yōu)秀!
這感覺就跟抄作業(yè)一樣。