ggplot2 包是 Hadly Wickham 開發(除 ggplot2 外,還有 plyr 和 reshape2 包)的一款通過 「+」,以圖層疊加的搭配組合,易於實現數據可視化的 R 包。ggplot2 以美輪美奐的統計製圖能力位居各類繪圖軟體排名前列,同時此包功能也在增加。此文簡單介紹 ggplot2 的基本原理和操作,便於大家對 ggplot2 快速入門。
ggplot() 作為泛型函數(gplot() 能快速作圖,卻不是泛型函數),能對任意類型的 R 對象進行可視化操作,這是 ggplot2 的精髓所在。
在 Hadly 的 ggplot2 官方文檔中,Hadely 這樣對 Wilkinson 的圖形語法進行了描述:「一張統計圖形就是從數據到集合對象(geometric object, 縮寫為 geom,包括點、線、條形等)的圖形屬性(aesthetic attributes, 縮寫為 aes, 包括顏色、形狀、大小等)的一個映射。此外,圖形中還可能包含數據的統計變換(statistical transformation, 縮寫為 stat),最後繪製在某個特定的坐標系(coordinate system, 縮寫為 coord)中,而分面(facet, 指將繪圖窗口劃分為若干個子窗口)則可以用來生成數據中不同子集的圖形。」 因此,在 ggplot2 中,圖形語法中至少包括了如下幾個圖形部件:
1、 數據(data)
2、 映射(mapping)
3、 幾何對象(geom)
4、 統計變換(stat)
5、 坐標系(coord)
6、 分面(facet)
7、 標度(scale)
這些組件之間用 「+」,以圖層(layer)的方式來粘合構圖的,所以圖層是 ggplot2 中一個重要的概念;在掌握基本的圖形部件基礎上,要完成一幅高質量的統計繪圖,仍然需要其他圖形部件來進一步擴展,這包括了:
8、 主題(theme)
9、 位置(position)
10、存儲和輸出
接下來將對上述概念展開講述
1、在 ggplot2 中,所接受的數據集必須為數據框(data.frame)格式。
如內置的 mtcars 數據集:head(mtcars)
2、這種數據框的格式好處是數據易於存儲,也能保留原有的繪圖參數下,用 %+% 方便地變更已有數據集。如:
library(ggplot2)p <- ggplot(mtcars,aes(mpg,wt,colour=cyl))+geom_point()p
mtcarsc <- transform(mtcars,mpg = mpg^2)p %+% mtcarsc
3、 ggplot2 進行數據分組時必須根據行, 而不能根據列。 例如在 mtcars 的數據集中, 可以把汽車按汽缸數進行分組, 但不能按汽車的檔位數和汽缸數這兩個變量分為兩組。這要求把 「寬」 數據轉化為 「長」 數據。所謂的長數據是變量不在是放在各個列上, 而是排成一列, 每一個變量都分別佔其中的幾行, 這樣就能方便的對每個變量進行分組。reshape2中 melt() 和 cast() 能夠靈活的融合 (melt) 和重鑄 (cast) 在數據框中的數據。如:
library(reshape2)mtcarsm <- melt(mtcars, id = c("mpg","disp","hp","drat","wt","qsec","vs","carb"))head(mtcarsm)
1、 概念
aes() 函數是 ggplot2 中的映射函數, 所謂的映射即為數據集中的數據關聯到相應的圖形屬性過程中一種對應關係, 如:
p1 <- ggplot(data = mtcars)summary(p1)
p2 <- ggplot(data = mtcars, mapping = aes(x = wt, y = hp, color = gear))summary(p2)
發現, 在 p2 中, 通過 aes() 指定了橫縱坐標分別為 wt 和 hp、 顏色為 gear 這三種圖形屬性。 在 ggplot2 中不同的幾何對象對應著不同的圖形屬性。
2、 設定和映射
映射是將一個變量中離散或連續的數據與一個圖形屬性中以不同的參數來相互關聯, 而設定能夠將這個變量中所有的數據統一為一個圖形屬性。如:
p <- ggplot(mtcars, aes(wt, mpg))#設定散點的顏色為藍色p + geom_point(color = "blue")
3、 分組(group)
分組也是 ggplot2 種映射關係的一種, 默認情況下 ggplot2 把所有觀測點分為了一組, 如果需要把觀測點按額外的離散變量進行分組處理, 必須修改默認的分組設置。
p3 <- ggplot(data = mtcars, mapping = aes(x = wt, y = hp)) + geom_line()p3
p4 <- ggplot(data = mtcars, mapping = aes(x = wt, y = hp, group = factor(gear))) + geom_line()p4
幾何對象執行著圖層的實際渲染, 控制著生成的圖像類型。例如用 geom_point() 將會生成散點圖, 而 geom_line 會生成折線圖。幾何對象如下:
具體應用如:
p <- ggplot(mtcars, aes(wt, mpg))p + geom_point()
#更改顏色-連續變量p + geom_point(aes(color = qsec))
#更改顏色-離散變量p + geom_point(aes(color = factor(gear)))
#更改透明度p + geom_point(aes(alpha = qsec))
#更改形狀p + geom_point(aes(shape = factor(gear)))
#更改點大小p + geom_point(aes(size = qsec))
#兩種顏色的疊加p + geom_point(color = "grey50", size = 5) + geom_point(aes(color = qsec), size = 4)
#顏色和形狀的疊加p +geom_point(color = "grey50", size = 5) + geom_point(aes(shape = factor(gear)), size = 3)
統計變換即對數據進行統計變化, 通常以某種方式對數據信息進行匯總, 例如通過 stat_smooth() 添加光滑曲線。統計對象如下:
每一個幾何對象都有一個默認的統計變換, 並且每一個統計變換都有一個默認的幾何對象。正因如此, 這一設定將會使繪圖過程變的靈活多變。
具體應用如:
m <- ggplot(mtcars, aes(qsec, wt))m + stat_smooth() + geom_point()
#取消默認的置信區間m + stat_smooth(se = FALSE) + geom_point()
#更改置信區間和線條顏色m + stat_smooth(fill = "red", size = 2, alpha = 0.5, color = "green") + geom_point()
#用一元一次線性方程擬合m + stat_smooth(method = "lm") + geom_point()
#使用一元二次方程擬合m + stat_smooth(method = "lm", formula = y ~ poly(x, 3)) + geom_point()
#按cyl這個離散變量進行分組, 分別擬合數據m <- ggplot(mtcars, aes(y = wt, x = mpg, group = factor(cyl)))m + stat_smooth(method = lm, aes(color = factor(cyl), fill = factor(cyl))) + geom_point( aes(color = factor(cyl)))
在上述對數據和映射的講解中, 已經採用過」+」 來添加圖層,可以這樣理解 ggplot2 中的圖層:每個圖層可以代表一個圖形組件, 如已經介紹的幾何對象、統計變換等圖形組件, 這些組件以圖層的方式疊加在一起構成一個繪圖的整體;在每個圖層中的圖形組件又可以分別設定數據、映射或其他相關參數, 因此組件之間又是具有相對獨立性的。ggplot2 中圖層的設定是十分成功的, 因為這一過程是如此實用、方便而富有邏輯性。
在幾何對象中設定映射
前面已在 ggplot() 中設定了映射了關係, 這種映射關係是默認的, 我們可以在後面的幾何對象中沿用已設定的默認映射關係, 也可以隨時在幾何對象中進行更改。
#設定默認的映射關係p <- ggplot(mtcars, aes(x = mpg, y = wt, color = factor(gear)))#沿用默認的映射關係來繪製散點圖p + geom_point()
#添加圖層中的shape的映射關係p + geom_point(aes(shape = factor(carb)))
#修改默認的y的映射關係, 注意圖中y軸名稱仍然以默認的wt表示p + geom_point(aes(y = carb))
#刪除默認的color映射關係p + geom_point(aes(color = NULL))
即在一個頁面上自動擺放多幅圖形, 這一過程先將數據劃分為多個子集, 然後將每個子集依次繪製到頁面的不同面板中。ggplot2 提供兩種分面類型:網格型 (facet_grid) 和封面型 (facet_wrap)。網格分面生成的是一個2 維的面板網格, 面板的行與列通過變量來定義, 本質是 2 維的; 封裝分面則先生成一個 1 維的面板條塊, 然後再分裝到 2 維中, 本質是 1 維的。分面函數如下:
在很多情況下, 我們可能需要繪製有兩個 y 軸的坐標系, 而在 ggplot2 中, 這種做法特別不提倡, 可解決的方法要麼是把變量歸一化, 要麼便是採用分面方法。如:
p <- ggplot(mtcars, aes(mpg, wt)) + geom_point()#以cyl為分類變量p + facet_grid(. ~ cyl)
#wrap與grid的區別p + facet_wrap( ~ cyl, nrow = 3)
p + facet_wrap( ~ cyl, ncol = 3)
p <- p + geom_smooth(method = "lm", se =F, aes(color = factor(cyl))) + geom_point(aes(color = factor(cyl)))p + facet_grid(vs ~ am)
主題系統控制著圖形中的非數據元素外觀, 它不會影響幾何對象和標度等數據元素。主題修改是一個對繪圖精雕細琢的過程, 主要對標題、坐標軸標籤、圖例標籤等文字調整, 以及網格線、背景、軸須的顏色搭配。
標度控制著數據到圖形屬性的映射, 更重要的一點是標度將我們的數據轉化為視覺上可以感知的東西, 如大小、顏色、位置和形狀。所以通過標度可以修改坐標軸和圖例的參數。標度函數如下:
位置函數
坐標系函數
經過以上過程講述,對 ggplot2 中的圖形語法有了基本了解,根據繪製圖形的效果可進行相對應的調參。
> p<-ggplot(mydata,aes(x=factor(time),y=mean,fill=treat))+geom_bar(position = "dodge",stat = "identity")
> p
# 初始的柱狀圖: factor()用於將數據從連續型轉為離散型(或者稱為「因子型」、「分類變量」),這樣橫軸就只有4和7兩個「刻度」,而不會像縱坐標軸那樣自動生成多個「刻度」。Fill用來分組,而"dodge"使組內的柱子「肩並肩」顯示。這一步的結果如下圖。
> p1<-ggplot(mydata,aes(x=factor(time),y=mean,fill=treat))+geom_bar(position =position_dodge(0.6),width = 0.5,stat = "identity")
> p1
#上圖的柱子太肥了,而且紅色和青色柱子間沒有間隙。這裡將利用position_dodge()增加柱子間隙,width更改柱子寬度,dodge()的數值比寬度稍大一點就有了空隙,如下圖。
> p2<-p1+geom_errorbar(aes(ymin=mean-se,ymax=mean+se),position=position_dodge(0.6),width=0.2)
> p2
# 添加誤差線,position_dodge(0.6)的數值要與上一步一致,以保持相對柱子居中,效果如下圖。
> p3<-p2+xlab("Time(d)")+ylab("Cell Growth Relative To Day1")
> p3
# 更改縱坐標軸的標題,去掉橫坐標軸的標題,結果如下圖。
> p4<-p3+scale_x_discrete(breaks=c(4,7),labels=c("4 Day", "7 Day"))
> p4
# 更改橫軸標籤,結果如下圖。注意,這裡用scale_x_continuous會報錯,因為x的數值類型已改為離散型。
> p5<-p4+geom_text(aes(x=factor(time),y=mean+se+0.08,group=treat,label=label),position = position_dodge(0.6))
> p5
# 給柱子加文本標籤(顯著性標記)。注意:這裡更準確的說法是給誤差線加標籤,巧妙的利用「y=mean+se(誤差線上端數值)+0.08(稍加點空隙)」確定文本標籤的位置,使它們隨誤差線起伏。position_dodge()的數值要和前面一致,以保持相對柱子居中。
> p6<-p5+scale_fill_manual(values=c("#ff6666", "#cc33ff"))
> p6
# 手動更改柱子的填充顏色,效果如下。
> p7<-p6+coord_cartesian(ylim = c(0.5,2.0),expand = FALSE)
> p7
# 更改y軸顯示範圍,對於柱狀圖如果直接+ylim(),雖然不會報錯,但柱子會消失,只剩下坐標軸(散點圖沒問題,被這個問題折騰好久)。這裡的expand默認為TRUE,改為FALSE就會按刻度範圍「切齊」,不會像上圖柱子下留出小部分區域。當然,我喜歡還是喜歡留一點區域,這裡僅做演示。
> mytheme<-theme_bw()
+theme(plot.title = element_text(size = rel(2),hjust = 0.5),axis.title = element_text(size = rel(1.2)),axis.text = element_text(size=rel(1.2)),panel.grid.major = element_line(color = "white"),panel.grid.minor = element_line(colour = "white"),axis.text.x = element_text(size = rel(1.2), color = "black"),axis.text.y = element_text(size = rel(1.2),color = "black"),legend.text = element_text(size = rel(1.2)),legend.title = element_blank())
>p6+mytheme
> ggsave("wanyixia.pdf", width = 20, height = 20, units = "cm")
# 修改主題,包括坐標軸標題、標籤文字的大小,顏色,去掉theme_bw()主題的網格線,去掉圖例的標題等,然後用ggsave()導出圖片,這裡保存為PDF格式,便於後期調整。最後的效果如下圖。
數據準備
set.seed(070511)
d <- data.frame(x = rnorm(2000))
基本直方圖
library(ggplot2)
ggplot(d, aes(x)) +
geom_histogram(bins = 50)
通過分組添加顏色
ggplot(d, aes(x, fill = cut(x, 100))) +
geom_histogram(bins = 50)
去掉圖列
ggplot(d, aes(x, fill = cut(x, 100))) +
geom_histogram(bins = 50,show.legend = FALSE)
調整色調
ggplot(d, aes(x, fill = cut(x, 100))) +
geom_histogram(show.legend = FALSE) +
scale_fill_discrete(h = c(250, 10))
調整飽和度和亮度
ggplot(d, aes(x, fill = cut(x, 100))) +
geom_histogram(show.legend = FALSE) +
scale_fill_discrete(h = c(240, 10), c = 120, l = 70)
設置主題
ggplot(d, aes(x, fill = cut(x, 100))) +
geom_histogram(show.legend = FALSE) +
scale_fill_discrete(h = c(240, 10), c = 120, l = 70) +
theme_minimal() +
labs(x = "Variable X", y = "n") +
ggtitle("Histogram of X")
為封面繪圖
p <- ggplot(d, aes(x, fill = cut(x, 100))) +
geom_histogram(show.legend = FALSE,bins = 50) +
theme_minimal() +
labs(x = "Variable X", y = "n") +
ggtitle("Histogram of X",subtitle = R.version.string)+
labs(caption = "zsrnog")
p + scale_fill_discrete(h = c(180, 360), c = 150, l = 80)+
theme(panel.background = element_rect(fill='black'),
#panel.border = element_rect(fill='black'),
plot.background = element_rect(fill='black'),
plot.title =element_text(colour = "blue"),
plot.subtitle=element_text(colour = "blue"),
plot.caption=element_text(colour = "blue"),
axis.line = element_line(colour = "grey80"),
axis.text = element_text(colour = "blue"),
axis.title = element_text(colour = "grey80"))
ggplot2 入門與進階:http://www.cellyse.com/how_to_use_gggplot2_part1/
R--ggplot2 包介紹學習:http://www.cnblogs.com/nxld/p/6059603.html
直播課程已經結束,掃碼免費聽錄播