ggplot2自定義繪圖主題

隨著ggplot2的粘滯性越來越強(qiáng),用它來完成一張草圖已經(jīng)不能滿足人們?nèi)找嬖鲩L的愛美之心了。其實(shí)ggplot2就是為美圖而生的蒸眠,為此甚至不惜從新定義了一套繪圖語法。他當(dāng)然有能力把我們送的更遠(yuǎn)杆融,不過要花我們的時(shí)間來看看如何自定義繪圖主題楞卡。

本文原文如下:

請(qǐng)進(jìn)

先看一下默認(rèn)主題是怎樣的:

The default theme
library(tidyverse)

ggplot(mpg, aes(x = class, y = cty)) +
  geom_boxplot(fill = "#6CB2EB", color = "#22292F",
               alpha = .8) +
  labs(
    title = "Stet clita kasd gubergren",
    subtitle = str_wrap(paste("Lorem ipsum dolor sit amet,",
                              "consetetur sadipscing elitr, sed diam",
                              "nonumy eirmod tempor invidunt ut labore",
                              "et dolore magna aliquyam erat, sed diam voluptua."), 
                        width = 80),
    caption = "Data: ggplot2; Visualization by Christian Burkhart"
  ) 

您可以立即看到這是一個(gè)ggplot2可視化,因?yàn)樗谢疑拿姘灞尘捌⑿DJ(rèn)主題的一個(gè)常見問題是axis文本太小蒋腮。元素之間幾乎沒有任何空間。因此藕各,可視化看起來非常密集池摧。要更改可視化,我們首先需要了解在ggplot2中主題化是如何工作的激况。我們的目標(biāo)是為所有可視化編寫一個(gè)全局主題作彤,這樣我們就不必為每個(gè)可視化調(diào)整主題膘魄。

可以使用theme_get函數(shù)查看默認(rèn)主題的所有設(shè)計(jì)。該函數(shù)返回一個(gè)非常長的字符串宦棺,因此我們只看一些設(shè)計(jì)元素瓣距。完整的列表,您可以查看官方文檔代咸。讓我們從軸文本開始:

theme_get()$axis.text
List of 11
 $ family       : NULL
 $ face         : NULL
 $ colour       : chr "grey30"
 $ size         : 'rel' num 0.8
 $ hjust        : NULL
 $ vjust        : NULL
 $ angle        : NULL
 $ lineheight   : NULL
 $ margin       : NULL
 $ debug        : NULL
 $ inherit.blank: logi TRUE
 - attr(*, "class")= chr [1:2] "element_text" "element"

axis文本總共有11個(gè)元素蹈丸。可以看到文本顏色設(shè)置為灰色呐芥。另外逻杖,字體大小設(shè)置為‘rel num 0.8’。Rel表示文本的大小是相對(duì)于相應(yīng)的父元素定義的,父元素是層次較高的元素思瘟。例如荸百,如果您在文本元素中全局定義文本大小,您將指定文本應(yīng)該只有父元素的80%大(更多信息可以在這里找到,here
)滨攻。

 theme_get()$panel.background:

List of 5
 $ fill         : chr "grey92"
 $ colour       : logi NA
 $ size         : NULL
 $ linetype     : NULL
 $ inherit.blank: logi TRUE
 - attr(*undefined "class")= chr [1:2] "element_rect" "element"

既然我們已經(jīng)知道了ggpplot2 主題的基本邏輯就可以開始我們的想象力了够话。

Set a global theme
ggplot(mpg, aes(x = class, y = cty)) +
  geom_boxplot(fill = "#6CB2EB", color = "#22292F",
               alpha = .8) +
  labs(
    title = "Stet clita kasd gubergren",
    subtitle = str_wrap(paste("Lorem ipsum dolor sit amet,",
                              "consetetur sadipscing elitr, sed diam",
                              "nonumy eirmod tempor invidunt ut labore",
                              "et dolore magna aliquyam erat, sed diam voluptua."), 
                        width = 80),
    caption = "Data: ggplot2; Visualization by Christian Burkhart"
  ) +
  theme(    panel.background = element_rect(color = "steelblue"),    axis.text        = element_text(size = rel(1.2))  )

這個(gè)過程只對(duì)單獨(dú)的可視化有意義。然而光绕,有些設(shè)計(jì)元素我們總是想要改變女嘲。例如,我們希望在每個(gè)可視化周圍添加填充诞帐,這樣文本就不會(huì)太靠近邊緣欣尼。我們也想使用我們學(xué)院的企業(yè)設(shè)計(jì)的某種字體。因此停蕉,我們必須找到全局定義樣式的方法愕鼓。

要全局定義主題,我們首先可以使用預(yù)定義的主題慧起。一種可能性是使用來自其他開發(fā)人員的包菇晃。例如,我是ggthemr包的粉絲蚓挤。要使用其中一個(gè)主題谋旦,你只需要添加一行代碼:

ggthemr('fresh', text_size = 18, layout = "scientific")
# Code for the plot goes here

這種可視化已經(jīng)看起來好多了。文本更大屈尼,更易讀册着。此外,可視化有自己的風(fēng)格脾歧,這是明確可識(shí)別的甲捏。然而,并不是所有元素都按照您希望的方式設(shè)計(jì)鞭执。例如司顿,我希望將右下角的標(biāo)題用較小的字體顯示芒粹,并使標(biāo)題的顏色更暗。

我們的問題的解決方案是函數(shù)theme_set大溜。使用theme_set化漆,我們可以定義自己的主題,并將其全局應(yīng)用于所有可視化钦奋。全局更改主題的最簡單方法是使用ggplot2的一個(gè)預(yù)定義主題.

theme_set(theme_minimal(base_size = 18))# Code for the plot goes here

我們使用的第一個(gè)技巧是更改文本大小座云。ggplot2中的每個(gè)預(yù)定義主題都有base_size參數(shù),我們可以使用它來更改文本大小付材。其他所有樣式都是由theme_minimum函數(shù)設(shè)置的朦拖。有了這個(gè)函數(shù),我們現(xiàn)在可以通過添加函數(shù)主題來設(shè)計(jì)每個(gè)元素厌衔。在下一個(gè)示例中璧帝,我們將使用繪圖為整個(gè)可視化添加填充。

theme_set(theme_minimal(base_size = 18) +
            theme(
              plot.margin = unit(rep(1, 4), "cm")
            ))
# Code for the plot goes here

修改圖中的字體也許太煩人了富寿,好在那是曾經(jīng)睬隶。我們還可以使用extrafont包更改可視化的字體。首先页徐,我們必須執(zhí)行函數(shù)font_import()來查找筆記本電腦上的所有字體。你只需要執(zhí)行這個(gè)函數(shù)一次泞坦。然后使用loadfonts()函數(shù)加載字體。您可以使用fonts()獲得所有字體的列表∽┣辏現(xiàn)在你可以選擇任何字體從這個(gè)列表和使用任何字體在你的主題:

#install.packages('extrafont')
library(extrafont)
font_import() # Run only once

#Continue? [y/n] y
#Scanning ttf files in C:\WINDOWS\Fonts ...
#Extracting .afm files from .ttf files...
#C:\Windows\Fonts\arial.ttf => E:/software/R/R-3.6.2/library/extrafontdb/metrics/arial
#C:\Windows\Fonts\arialbd.ttf => E:/software/R/R-3.6.2/library/extrafontdb/metrics/arialbd
#C:\Windows\Fonts\arialbi.ttf => E:/software/R/R-3.6.2/library/extrafontdb/metrics/arialbi

loadfonts() # Run only once
fonts() # Show a list of all fonts
 [1] "Arial Black"             "Arial"                   "Bahnschrift"             "Calibri"                 "Calibri Light"           "Cambria"                
 [7] "Candara"                 "Candara Light"           "Comic Sans MS"           "Consolas"                "Constantia"              "Corbel"                 
[13] "Corbel Light"            "Courier New"             "DejaVu Sans Mono"        "DengXian"                "DengXian Light"          "Ebrima"                 
[19] "FangSong"                "Franklin Gothic Medium"  "FZCuHeiSongS-B-GB"       "Gabriola"                "Gadugi"                  "Georgia"                
[25] "HoloLens MDL2 Assets"    "HP Simplified"           "HP Simplified Light"     "Impact"                  "Ink Free"                "Javanese Text"          
[31] "KaiTi"                   "Leelawadee UI"           "Leelawadee UI Semilight" "Lucida Console"          "Lucida Sans Unicode"     "Malgun Gothic"          
[37] "Malgun Gothic Semilight" "Marlett"                 "Microsoft Himalaya"      "Microsoft Yi Baiti"      "Microsoft New Tai Lue"   "Microsoft PhagsPa"      
[43] "Microsoft Sans Serif"    "Microsoft Tai Le"        "Mongolian Baiti"         "MV Boli"                 "Myanmar Text"            "Nirmala UI"             
[49] "Nirmala UI Semilight"    "NumberOnly"              "Palatino Linotype"       "Segoe MDL2 Assets"       "Segoe Print"             "Segoe Script"           
[55] "Segoe UI"                "Segoe UI Light"          "Segoe UI Semibold"       "Segoe UI Semilight"      "Segoe UI Black"          "Segoe UI Emoji"         
[61] "Segoe UI Historic"       "Segoe UI Symbol"         "SimHei"                  "SimSun-ExtB"             "Sylfaen"                 "Symbol"                 
[67] "Tahoma"                  "Times New Roman"         "Trebuchet MS"            "Verdana"                 "Webdings"                "Wingdings"              
> theme_set(theme_minimal(base_size = 18, 

theme_set(theme_minimal(base_size = 18, 
base_family = "Segoe UI") +            theme(
  plot.margin = unit(rep(1, 4), "cm")
))
# Code for the plot goes here
Create your own global themes

現(xiàn)在我們知道了如何全局更改元素贰锁,可以創(chuàng)建自己的主題了。在下一個(gè)示例中滤蝠,您可以找到我設(shè)計(jì)的主題豌熄。我確保元素之間有足夠的空白,并且字體足夠大物咳,所有讀者都可以閱讀锣险。我還將主題放在一個(gè)函數(shù)中,以便您以后可以輕松地在不同的主題之間切換览闰。

base_theme <- theme(
  plot.margin = unit(rep(1, 4), "cm"),
  plot.title = element_text(size = 24, 
                            face = "bold",
                            color = "#22292F", 
                            margin = margin(b = 8)),
  plot.subtitle = element_text(size = 16, 
                               lineheight = 1.1,
                               color = "#22292F",
                               margin = margin(b = 25)),
  plot.caption = element_text(size = 12,
                              margin = margin(t = 25), 
                              color = "#3D4852"),
  axis.title.x = element_text(margin = margin(t = 15)),
  axis.title.y = element_text(margin = margin(r = 15)),
  axis.text = element_text(color = "#22292F")
) 

set_base_theme <- function() {
  theme_set(theme_minimal(base_size = 18) +
              base_theme)
}
set_base_theme()
# Code for the plot goes here

對(duì)于可視化芯肤,我使用字體Segoe。現(xiàn)在您已經(jīng)了解了原理压鉴,您可以根據(jù)自己的喜好定制主題崖咨。我發(fā)現(xiàn)寫一個(gè)適用于所有可視化的基本主題是很方便的。其他主題都是基于基本主題油吭。例如击蹲,在接下來的可視化中署拟,我嘗試從ggthemr包中重新創(chuàng)建一個(gè)主題:

flat_theme <- theme(
  panel.background = element_rect(fill = "#f3f6f6", color = NA),
  panel.grid = element_line(color = "#cacfd2", linetype = "dashed"),
  axis.line = element_line(color = "#606F7B")
)

set_flat_theme <- function() {
  theme_set(theme_minimal(base_size = 18) +
              base_theme +
              flat_theme)
}

set_flat_theme()
# Code for the plot goes here

從代碼中可以看到,我已經(jīng)將flat_theme添加到了base_theme中歌豺。兩個(gè)變量都包含主題函數(shù)推穷。原則上,我還可以添加第三個(gè)主題类咧。在上一個(gè)例子中馒铃,我創(chuàng)建了一個(gè)全局黑暗主題:

dark_theme <- theme(
  plot.margin = unit(rep(1, 4), "cm"),
  plot.title = element_text(size = 24, 
                            face = "bold",
                            color = "#22292F", 
                            margin = margin(b = 8)),
  plot.subtitle = element_text(size = 16, 
                               lineheight = 1.1,
                               color = "#22292F",
                               margin = margin(b = 25)),
  plot.caption = element_text(size = 12,
                              margin = margin(t = 25), 
                              color = "#3D4852"),
  axis.title.x = element_text(margin = margin(t = 15)),
  axis.title.y = element_text(margin = margin(r = 15)),
  axis.text = element_text(color = "#22292F"),
  panel.background = element_rect("#34495e", color = NA),
  panel.grid = element_line(color = "#49637a")
) 

set_dark_theme <- function() {
  theme_set(theme_minimal(base_size = 18,
                          base_family = "Segoe UI") +
              dark_theme)
}
set_dark_theme()

對(duì)于暗主題,我們必須更改geoms以使可視化變得可讀轮听。在本例中骗露,我用淺綠色對(duì)箱形圖進(jìn)行了樣式設(shè)置。注意血巍,我還使用theme函數(shù)在可視化代碼中更改了主題萧锉,因?yàn)椴⒉皇撬械目梢暬亩夹枰侨值摹@缡龉眩覜Q定只在x軸上顯示網(wǎng)格:

ggplot(mpg, aes(x = class, y = cty)) +
  geom_boxplot(fill = "#64D5CA", color = "#ffffff",
               alpha = .8) +
  labs(
    title = "Stet clita kasd gubergren",
    subtitle = str_wrap(paste("Lorem ipsum dolor sit amet,",
                              "consetetur sadipscing elitr, sed diam",
                              "nonumy eirmod tempor invidunt ut labore",
                              "et dolore magna aliquyam erat, sed diam voluptua."), 
                        width = 80),
    caption = "Data: ggplot2; Visualization by Christian Burkhart"
  ) +
  theme(
    panel.grid.major.x = element_blank(),
    panel.grid.minor.x = element_blank(),
    panel.grid.minor.y = element_blank()
  )

下一步柿隙,我建議您嘗試使用此模板并創(chuàng)建自己的自定義主題。創(chuàng)建您自己的主題可能會(huì)花費(fèi)您一些工作鲫凶,但是稍后您將不必為每個(gè)單獨(dú)的可視化定制主題禀崖。您可能仍然想知道在哪里存儲(chǔ)這些主題,而不必編寫包螟炫。一個(gè)解決方案是將你的主題復(fù)制到每一個(gè)r文件波附,但這將是重復(fù)的。我建議您在項(xiàng)目中創(chuàng)建一個(gè)單獨(dú)的文件來存儲(chǔ)主題昼钻。你可以把這個(gè)文件讀入R后使用的源函數(shù):

source("set_themes.R")

思考掸屡,如果設(shè)置了全局主題,如何在應(yīng)用避免他呢然评,如果我想的話仅财?

ggthemr_reset()

ggthemr 知乎

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市碗淌,隨后出現(xiàn)的幾起案子盏求,更是在濱河造成了極大的恐慌,老刑警劉巖亿眠,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碎罚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡纳像,警方通過查閱死者的電腦和手機(jī)魂莫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爹耗,“玉大人耙考,你說我怎么就攤上這事谜喊。” “怎么了倦始?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵斗遏,是天一觀的道長。 經(jīng)常有香客問我鞋邑,道長诵次,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任枚碗,我火速辦了婚禮逾一,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肮雨。我一直安慰自己遵堵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布怨规。 她就那樣靜靜地躺著陌宿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪波丰。 梳的紋絲不亂的頭發(fā)上壳坪,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音掰烟,去河邊找鬼爽蝴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛纫骑,可吹牛的內(nèi)容都是我干的蝎亚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼惧磺,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了捻撑?” 一聲冷哼從身側(cè)響起磨隘,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎顾患,沒想到半個(gè)月后番捂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡江解,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年设预,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了犁河。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鳖枕。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡魄梯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宾符,到底是詐尸還是另有隱情酿秸,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布魏烫,位于F島的核電站辣苏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏哄褒。R本人自食惡果不足惜稀蟋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望呐赡。 院中可真熱鬧退客,春花似錦、人聲如沸罚舱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽管闷。三九已至粥脚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間包个,已是汗流浹背刷允。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碧囊,地道東北人树灶。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像糯而,于是被迫代替她去往敵國和親天通。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容