您的位置:首頁>正文

ggplot2學習筆記之——ggplot2主題調整系統

作者:杜雨 R語言中文社區專欄作者

個人公眾號:數據小魔方(微信ID:datamofang)

ggplot2繪圖系統擁有龐大、健全的圖形美化系統, 這一套圖形美化依賴於圖例調整系統、標度調整系統、標籤調整系統、主題調整系統以及分面系統。

本節僅從主題調整系統來淺析ggplot2是如何實現脫離資料層面的資訊, 單獨實現主題調整系統的。

從大的層面上來說, ggplot2的主題系統知識主要分為三個層面:

一、主題調整函數:

二、元素調整函數:

三、元素調整參數:

主題調整函數很好理解, 就是用於封裝主題的函數, 可以是預設主題(系統預設的主題函數)、也可以是協力廠商介面包提供的定制主題(如ggthemes包、ggtech包、ggsci包等)、或者是自己通過主題調整函數自訂的主題。

ggplot2的預設主題是theme_gray(),也即你在繪製圖形的時候, 即便不指定主題, 預設調用的也是這款主題。

你可以通過theme_get()函數獲取當前主題的所有參數配置清單, 當然直接運行theme_gray()函數【這裡要注意運行theme_gray()和運行theme_gray獲取的結果是不一樣的, 執行theme_gray()是運行一個函數, 返回的是一個清單格式的主題參數配置物件, 而直接運行theme_gray則是列印出了theme_gray函數本身的語句資訊, 這一點兒需要區分清楚, 函數本身與函數物件輸出結果是截然不同的兩個物件】時, 同樣可以得到這主題的參數配置清單。

p <- ggplot(mtcars) + geom_point(aes(x = wt, y = mpg, colour = factor(gear))) + facet_wrap(~am)p + theme_gray() # the default

theme_set(new) 函數很特別, 它接受一個新定義的主題同時, 會將系統系統預設主題靜默返回, 這樣你在使用時需將這個函數指定為一個臨時物件, 以便自訂主題使用之後, 方便回復系統之前的預設主題。 (如果不存儲反悔的舊主題的話, 那麼系統就無法恢復到當預設主題了【當然重新開機系統就恢復了】)。

p <- ggplot(mtcars, aes(mpg, wt)) + geom_point();pold <- theme_set(theme_bw());ptheme_set(old);p

theme_update()函數和theme_replace()函數是一對相愛相殺的函數, 兩者存在著微妙的關係,也是涉獵不神的初學者最容易困惑的兩個主題函數。

這裡澄清一下(也是參考ggplot2官網上的原文解釋),theme_update()與theme_replace()函數都可以起到修改主題的作用,但是不同的是二者在修改主題的時候作用方式不同。

theme_update()函數是一種增量更新,也即在預設主題的基礎上,對比與theme_update()函數內部各個主題參數之間的差異,有差異的以新增的為主,無差異的則保持不變。

而theme_replace()函數則更為霸道,它是一種全量更新,即在預設主題的基礎上,比對與theme_replace()函數內部主題參數之間的差異,有差異則以後者為准,但是theme_replace()函數內部沒有生命的所有參數(也即你未指定的那些元素參數)都會被初始化為NULL,也即只應用你顯式聲明的那些自訂參數,為生命的都會被清空,較為霸道。

這兩者解釋清楚了,那麼下一個問題又來了,看到之前寫過的代碼,有時候我使用主題函數用的 + theme(),有時候則用的是 %+replace% theme(),這兩者又有什麼區別呢,這兩者與上面提到過的theme_update()與theme_replace()函數是否有關聯呢。

其實還真的有關聯,這裡直接說結論。

theme_update() 等價於 theme_gray() + theme(),theme()函數內部的參數會替換theme_gray()內部的同名參數,未聲明的則保持不變。

theme_replace() 等價於 theme_gray() %+replace% theme(),theme()函數內部的參數會替換theme_gray()內部的同名參數,未聲明的參數全部初始化為NULL。

所以你也可以理解為,theme_update()直接作用於當前主題,theme_replace()則是僅僅使用顯式聲明的主題元素外,所有未聲明的都清空。

這便是這兩組函數的區別于關聯,通常來講,用哪一組是習慣問題,單也要看場景,你是需要所有元素都重新修改,還是只要修改其中某幾個元素。

add_el <- theme_grey() + theme(text = element_text(family = "Times"))add_el$text#> List of 11#> $ family : chr "Times"#> $ face : chr "plain"#> $ colour : chr "black"#> $ size : num 11#> $ hjust : num 0.5#> $ vjust : num 0.5#> $ angle : num 0#> $ lineheight : num 0.9#> $ margin :Classes 'margin', 'unit' atomic [1:4] 0 0 0 0#> .. ..- attr(*, "valid.unit")= int 8#> .. ..- attr(*, "unit")= chr "pt"#> $ debug : logi FALSE#> $ inherit.blank: logi FALSE#> - attr(*, "class")= chr [1:2] "element_text" "element"rep_el <- theme_grey() %+replace% theme(text = element_text(family = "Times"))rep_el$text#> List of 11#> $ family : chr "Times"#> $ face : NULL#> $ colour : NULL#> $ size : NULL#> $ hjust : NULL#> $ vjust : NULL#> $ angle : NULL#> $ lineheight : NULL#> $ margin : NULL#> $ debug : NULL#> $ inherit.blank: logi FALSE#> - attr(*, "class")= chr [1:2] "element_text" "element"

ggplot2的主題元素函數主要有四大類(其實是三大類):

element_text()element_rect()element_line()element_blank()

這些函數很好理解,分別是文本類型、矩形區域、線條類型等。最後一個只是為了方便清空某類主題元素而設計的。

這三類主題元素函數將所有的ggplot2圖形主題元素全部都抽象進去了,而且做了嚴格的子孫繼承關係鏈與許可權控制範圍。

從text、rect、line這三個全域主題元素到之後的各個主題模組的各類text、rect、line及其衍生主題,都遵循這種子孫繼承關係。

比如你制定了text = element_text(family= ,size = ,angle = , colour = )嗎,那麼所有的模組涉及到主題文本元素的都會強制遵守這些參數,如果僅僅是為了修改某一個模組的局部文本元素,你絕對不可以設置這麼高級別的文本調整函數,而是直接定位到局部主題文本調整函數進行對應的參數設置即可,比如 Axis.title.y = element_text(family= ,size = ,angle = , colour = ),類似這種控制許可權,rect和line都是遵從的。

整個繼承關係鏈可以參考這個圖。

這些參數在ggplot2的官方文檔上都寫的清清楚楚、明明白白。

除了主題元素調整 函數之外,第三塊內容當然就是這些主題元素調整函數內部的元素參數啦~

這些元素參數都是高度抽象化、統一化的,也意味著很多都是通用的,與美學映射內的參數看齊的。

--------------element_text()----------------------------------------------------Argument Description Default Value-----------------------------------------------------family font family ""face font face "plain"colour font color "black"size font size(pts) 10hjust horizontal justification 0.5vjust vertical justification 0.5angle text angle 0lineheight line height 1.1--------------element_line()-----------------------------------------------------Argument Description Default Value-------------------------------------------------------colour line color "black"size line thickness 0.5linetype type of line 1--------------element_rect()---------------------------------------------------Argument Description Default Value---------------------------------------------------fill fill color NA(none)colour border color "black"size thickness of border line 0.5linetype type of border line 1(solid)-----------------------------------------------------

講了這麼多,一個案例來複習下:

library("ggplot2")library("reshape2")library("ggthemes")library("magrittr")mydata <- data.frame( Name = c("蘋果","穀歌","臉書","亞馬遜","騰訊"), Company = c("Apple","Google","Facebook","Amozon","Tencent"), Sale2013 = c(5000,3500,2300,2100,3100), Sale2014 = c(5050,3800,2900,2500,3300), Sale2015 = c(5050,3800,2900,2500,3300), Sale2016 = c(5050,3800,2900,2500,3300) ) %>% melt( id.vars=c("Name","Company"), variable.name="Year", value.name="Sale" )#預設主題ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity")#預設主題(theme_gray())ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity")+ theme_gray()

預設主題1

ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity") +theme_bw()

自訂封裝主題函數:

###方法一:windowsFonts( myFont = windowsFont("微軟雅黑"))theme_xmf <- theme_replace( plot.title = element_text(size = 20,family="myFont",hjust = 0,lineheight = 2), plot.subtitle = element_text(size = 15,family="myFont",hjust = 0,lineheight = 2), plot.caption = element_text(size = 18,family="myFont",hjust = 0,lineheight = 2), plot.background = element_rect( fill = '#efefef',size = 0.8 ,linetype = 3, color = 'grey'), plot.margin = margin(10,5,10,5,unit="pt"), legend.position = "top" , panel.border = element_blank(), panel.background = element_rect(fill = '#d4dee7',size = 2 ,linetype = 3, color = 'grey'), panel.grid.major = element_line(linetype = "dashed"), panel.grid.minor = element_blank(), axis.line = element_line(size = 1.2 , colour = 'black',linetype = 1), axis.text = element_text(size=10,colour="#003087",family="myFont"), legend.text = element_text(size=9,colour="#003087",family="myFont"), legend.key = element_blank())ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity") + scale_fill_brewer(palette="Blues") + guides(fill = guide_legend(reverse = TRUE)) + labs( title = '這裡是主標題', subtitle = '這裡是副標題', caption = '這裡是備註' ) + theme_xmf

方法2

theme_manual <- function(){ theme_get() %+replace% theme( plot.title = element_text(size = 20,family="myFont",hjust = 0,lineheight = 2), plot.subtitle = element_text(size = 15,family="myFont",hjust = 0,lineheight = 2), plot.caption = element_text(size = 18,family="myFont",hjust = 0,lineheight = 2), plot.background = element_rect(fill = '#efefef',size = 0.8 ,linetype = 3, color = 'grey'), plot.margin = margin(10,5,10,5,unit="pt"), legend.position="top", panel.border=element_blank(), panel.background = element_rect(fill = '#d4dee7',size = 2 ,linetype = 3, color = 'grey'), panel.grid.major=element_line(linetype="dashed"), panel.grid.minor=element_blank(), axis.line = element_line(size = 1.2 , colour = 'black',linetype = 1), axis.text=element_text(size=10,colour="#003087",family="myFont"), legend.text=element_text(size=9,colour="#003087",family="myFont"), legend.key=element_blank() )}ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity") + scale_fill_brewer(palette="Blues") + guides(fill = guide_legend(reverse = TRUE)) + labs( title = '這裡是主標題', subtitle = '這裡是副標題', caption = '這裡是備註' ) + theme_manual()

是不是要比原生的主題要更加簡潔、專業一些呢~

一句老套的話,要想學到真功夫,要下定決心去啃來源文件~

http://ggplot2.tidyverse.org/reference/

當然如果你想要深入的去學ggplot2,但是又苦於平時學習、工作太忙木有時間研究浩如煙海的來源文件,那也沒關係,本小編最近花了不少功夫,把我自己學習ggplot2過程中的一些心得體會、學習經驗、仿入坑指南精心整理,現已成功上線了R語言ggplot2視覺化的視頻課程,由天善智慧獨家發行,希望這門課程可以給你的R語言資料視覺化學習帶來更加豐富的體驗。

兩者存在著微妙的關係,也是涉獵不神的初學者最容易困惑的兩個主題函數。

這裡澄清一下(也是參考ggplot2官網上的原文解釋),theme_update()與theme_replace()函數都可以起到修改主題的作用,但是不同的是二者在修改主題的時候作用方式不同。

theme_update()函數是一種增量更新,也即在預設主題的基礎上,對比與theme_update()函數內部各個主題參數之間的差異,有差異的以新增的為主,無差異的則保持不變。

而theme_replace()函數則更為霸道,它是一種全量更新,即在預設主題的基礎上,比對與theme_replace()函數內部主題參數之間的差異,有差異則以後者為准,但是theme_replace()函數內部沒有生命的所有參數(也即你未指定的那些元素參數)都會被初始化為NULL,也即只應用你顯式聲明的那些自訂參數,為生命的都會被清空,較為霸道。

這兩者解釋清楚了,那麼下一個問題又來了,看到之前寫過的代碼,有時候我使用主題函數用的 + theme(),有時候則用的是 %+replace% theme(),這兩者又有什麼區別呢,這兩者與上面提到過的theme_update()與theme_replace()函數是否有關聯呢。

其實還真的有關聯,這裡直接說結論。

theme_update() 等價於 theme_gray() + theme(),theme()函數內部的參數會替換theme_gray()內部的同名參數,未聲明的則保持不變。

theme_replace() 等價於 theme_gray() %+replace% theme(),theme()函數內部的參數會替換theme_gray()內部的同名參數,未聲明的參數全部初始化為NULL。

所以你也可以理解為,theme_update()直接作用於當前主題,theme_replace()則是僅僅使用顯式聲明的主題元素外,所有未聲明的都清空。

這便是這兩組函數的區別于關聯,通常來講,用哪一組是習慣問題,單也要看場景,你是需要所有元素都重新修改,還是只要修改其中某幾個元素。

add_el <- theme_grey() + theme(text = element_text(family = "Times"))add_el$text#> List of 11#> $ family : chr "Times"#> $ face : chr "plain"#> $ colour : chr "black"#> $ size : num 11#> $ hjust : num 0.5#> $ vjust : num 0.5#> $ angle : num 0#> $ lineheight : num 0.9#> $ margin :Classes 'margin', 'unit' atomic [1:4] 0 0 0 0#> .. ..- attr(*, "valid.unit")= int 8#> .. ..- attr(*, "unit")= chr "pt"#> $ debug : logi FALSE#> $ inherit.blank: logi FALSE#> - attr(*, "class")= chr [1:2] "element_text" "element"rep_el <- theme_grey() %+replace% theme(text = element_text(family = "Times"))rep_el$text#> List of 11#> $ family : chr "Times"#> $ face : NULL#> $ colour : NULL#> $ size : NULL#> $ hjust : NULL#> $ vjust : NULL#> $ angle : NULL#> $ lineheight : NULL#> $ margin : NULL#> $ debug : NULL#> $ inherit.blank: logi FALSE#> - attr(*, "class")= chr [1:2] "element_text" "element"

ggplot2的主題元素函數主要有四大類(其實是三大類):

element_text()element_rect()element_line()element_blank()

這些函數很好理解,分別是文本類型、矩形區域、線條類型等。最後一個只是為了方便清空某類主題元素而設計的。

這三類主題元素函數將所有的ggplot2圖形主題元素全部都抽象進去了,而且做了嚴格的子孫繼承關係鏈與許可權控制範圍。

從text、rect、line這三個全域主題元素到之後的各個主題模組的各類text、rect、line及其衍生主題,都遵循這種子孫繼承關係。

比如你制定了text = element_text(family= ,size = ,angle = , colour = )嗎,那麼所有的模組涉及到主題文本元素的都會強制遵守這些參數,如果僅僅是為了修改某一個模組的局部文本元素,你絕對不可以設置這麼高級別的文本調整函數,而是直接定位到局部主題文本調整函數進行對應的參數設置即可,比如 Axis.title.y = element_text(family= ,size = ,angle = , colour = ),類似這種控制許可權,rect和line都是遵從的。

整個繼承關係鏈可以參考這個圖。

這些參數在ggplot2的官方文檔上都寫的清清楚楚、明明白白。

除了主題元素調整 函數之外,第三塊內容當然就是這些主題元素調整函數內部的元素參數啦~

這些元素參數都是高度抽象化、統一化的,也意味著很多都是通用的,與美學映射內的參數看齊的。

--------------element_text()----------------------------------------------------Argument Description Default Value-----------------------------------------------------family font family ""face font face "plain"colour font color "black"size font size(pts) 10hjust horizontal justification 0.5vjust vertical justification 0.5angle text angle 0lineheight line height 1.1--------------element_line()-----------------------------------------------------Argument Description Default Value-------------------------------------------------------colour line color "black"size line thickness 0.5linetype type of line 1--------------element_rect()---------------------------------------------------Argument Description Default Value---------------------------------------------------fill fill color NA(none)colour border color "black"size thickness of border line 0.5linetype type of border line 1(solid)-----------------------------------------------------

講了這麼多,一個案例來複習下:

library("ggplot2")library("reshape2")library("ggthemes")library("magrittr")mydata <- data.frame( Name = c("蘋果","穀歌","臉書","亞馬遜","騰訊"), Company = c("Apple","Google","Facebook","Amozon","Tencent"), Sale2013 = c(5000,3500,2300,2100,3100), Sale2014 = c(5050,3800,2900,2500,3300), Sale2015 = c(5050,3800,2900,2500,3300), Sale2016 = c(5050,3800,2900,2500,3300) ) %>% melt( id.vars=c("Name","Company"), variable.name="Year", value.name="Sale" )#預設主題ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity")#預設主題(theme_gray())ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity")+ theme_gray()

預設主題1

ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity") +theme_bw()

自訂封裝主題函數:

###方法一:windowsFonts( myFont = windowsFont("微軟雅黑"))theme_xmf <- theme_replace( plot.title = element_text(size = 20,family="myFont",hjust = 0,lineheight = 2), plot.subtitle = element_text(size = 15,family="myFont",hjust = 0,lineheight = 2), plot.caption = element_text(size = 18,family="myFont",hjust = 0,lineheight = 2), plot.background = element_rect( fill = '#efefef',size = 0.8 ,linetype = 3, color = 'grey'), plot.margin = margin(10,5,10,5,unit="pt"), legend.position = "top" , panel.border = element_blank(), panel.background = element_rect(fill = '#d4dee7',size = 2 ,linetype = 3, color = 'grey'), panel.grid.major = element_line(linetype = "dashed"), panel.grid.minor = element_blank(), axis.line = element_line(size = 1.2 , colour = 'black',linetype = 1), axis.text = element_text(size=10,colour="#003087",family="myFont"), legend.text = element_text(size=9,colour="#003087",family="myFont"), legend.key = element_blank())ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity") + scale_fill_brewer(palette="Blues") + guides(fill = guide_legend(reverse = TRUE)) + labs( title = '這裡是主標題', subtitle = '這裡是副標題', caption = '這裡是備註' ) + theme_xmf

方法2

theme_manual <- function(){ theme_get() %+replace% theme( plot.title = element_text(size = 20,family="myFont",hjust = 0,lineheight = 2), plot.subtitle = element_text(size = 15,family="myFont",hjust = 0,lineheight = 2), plot.caption = element_text(size = 18,family="myFont",hjust = 0,lineheight = 2), plot.background = element_rect(fill = '#efefef',size = 0.8 ,linetype = 3, color = 'grey'), plot.margin = margin(10,5,10,5,unit="pt"), legend.position="top", panel.border=element_blank(), panel.background = element_rect(fill = '#d4dee7',size = 2 ,linetype = 3, color = 'grey'), panel.grid.major=element_line(linetype="dashed"), panel.grid.minor=element_blank(), axis.line = element_line(size = 1.2 , colour = 'black',linetype = 1), axis.text=element_text(size=10,colour="#003087",family="myFont"), legend.text=element_text(size=9,colour="#003087",family="myFont"), legend.key=element_blank() )}ggplot(mydata,aes(Company,Sale,fill=Year))+ geom_bar(stat="identity") + scale_fill_brewer(palette="Blues") + guides(fill = guide_legend(reverse = TRUE)) + labs( title = '這裡是主標題', subtitle = '這裡是副標題', caption = '這裡是備註' ) + theme_manual()

是不是要比原生的主題要更加簡潔、專業一些呢~

一句老套的話,要想學到真功夫,要下定決心去啃來源文件~

http://ggplot2.tidyverse.org/reference/

當然如果你想要深入的去學ggplot2,但是又苦於平時學習、工作太忙木有時間研究浩如煙海的來源文件,那也沒關係,本小編最近花了不少功夫,把我自己學習ggplot2過程中的一些心得體會、學習經驗、仿入坑指南精心整理,現已成功上線了R語言ggplot2視覺化的視頻課程,由天善智慧獨家發行,希望這門課程可以給你的R語言資料視覺化學習帶來更加豐富的體驗。

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示