9 圖形排列
ggplot2 中提供的語(yǔ)法與創(chuàng)建單個(gè)圖有關(guān)胧后。雖然分面系統(tǒng)提供了生成多個(gè)子圖的方法肴盏,但所有這些都主要都是可視化科盛、共享層、數(shù)據(jù)和比例的一部分菜皂。然而贞绵,通常需要使用多個(gè)不同的圖形來(lái)講述一個(gè)故事或提出一個(gè)論點(diǎn)。這些當(dāng)然可以單獨(dú)創(chuàng)建并在布局程序中組裝恍飘,但在代碼中執(zhí)行此操作是有益的但壮,以避免耗時(shí)且不可重復(fù)的工作。一系列的方案應(yīng)運(yùn)而生常侣,提供了安排不同圖形的不同方法。雖然本章將重點(diǎn)介紹 patchwork 包弹渔,但您也可以在 cowplot胳施、gridExtra 和 ggpubr 包中找到一些相同的功能。
本章將分為兩部分肢专。第一種方法是將圖形塊并排排列而不重疊舞肆,而第二種方法是將圖形塊依次排列。雖然這兩種方案不一定是相互對(duì)立的博杖,但前一種情況通常會(huì)受益于后一種情況下沒(méi)有意義的功能椿胯,例如繪圖區(qū)域的對(duì)齊。
9.1 圖形并排
通常剃根,人們希望并排展示兩個(gè)或更多圖形哩盲,從不同方面展示同一故事。這是拼湊而成的場(chǎng)景來(lái)解決。從本質(zhì)上講廉油,patchwork 是一個(gè)包惠险,它對(duì)ggplot2擴(kuò)展了 +
操作符的使用以在多個(gè)圖之間工作,并為專門的組合添加額外的操作符和處理圖的組合抒线。
作為patchwork最基本用法的示例班巩,我們將使用mpg
數(shù)據(jù)集的以下4個(gè)圖
p1 <- ggplot(mpg) +
geom_point(aes(x = displ, y = hwy))
p2 <- ggplot(mpg) +
geom_bar(aes(x = as.character(year), fill = drv), position = "dodge") +
labs(x = "year")
p3 <- ggplot(mpg) +
geom_density(aes(x = hwy, fill = drv), colour = NA) +
facet_grid(rows = vars(drv))
p4 <- ggplot(mpg) +
stat_summary(aes(x = drv, y = hwy, fill = drv), geom = "col", fun.data = mean_se) +
stat_summary(aes(x = drv, y = hwy), geom = "errorbar", fun.data = mean_se, width = 0.5)
拼湊最簡(jiǎn)單的用法是+
將繪圖添加到一起,從而創(chuàng)建一組要顯示在一起的繪圖:
library(patchwork)
p1 + p2
+
沒(méi)有指定任何特定的布局嘶炭,只是應(yīng)該將圖一起顯示抱慌。在沒(méi)有布局的情況下,控制facet_wrap()中行數(shù)和列數(shù)的相同算法將決定行數(shù)和列數(shù)眨猎。這意味著將 3 個(gè)圖加在一起將創(chuàng)建一個(gè) 1x3 網(wǎng)格抑进,而將 4 個(gè)圖加在一起將創(chuàng)建一個(gè) 2x2 網(wǎng)格。
p1 + p2 + p3 + p4
從上面的兩個(gè)例子可以看出宵呛,patchwork 負(fù)責(zé)將圖的不同部分相互對(duì)齊单匣。您可以看到所有繪圖區(qū)域都是對(duì)齊的,即使存在分面也是如此宝穗。此外户秤,您可以看到盡管左下圖中的軸文本更寬,但最左側(cè)的兩個(gè)圖中的 y 軸標(biāo)題已對(duì)齊逮矛。
9.1.1 布局控制
通常自動(dòng)創(chuàng)建的網(wǎng)格不是您想要的鸡号,當(dāng)然可以控制它。最直接须鼎、最強(qiáng)大的方法是在``plot`中添加一個(gè)plot_layout()規(guī)范:
p1 + p2 + p3 + plot_layout(ncol = 2)
一個(gè)常見(jiàn)的場(chǎng)景是想要強(qiáng)制單行或單列鲸伴。拼縫提供了兩個(gè)操作員,/
并|
分別以促進(jìn)此(引擎蓋下他們只是組的行或列中的布局編號(hào)為1)晋控。
一種常見(jiàn)的場(chǎng)景是希望強(qiáng)制執(zhí)行單個(gè)行或列汞窗。Patchwork分別提供了兩個(gè)操作符/
和|
來(lái)實(shí)現(xiàn)這一點(diǎn)(實(shí)際上它們只是將布局中的行數(shù)或列數(shù)設(shè)置為1)。
p1 / p2
# Basically the same as using `+` but the intend is clearer
p3 | p4
patchwork 允許布局嵌套赡译,這意味著僅使用這兩個(gè)運(yùn)算符就可以生成一些非常復(fù)雜的布局
p3 | (p2 / (p1 | p4))
另外仲吏,對(duì)于非常復(fù)雜的布局,也可以在plot_layout()
的design
參數(shù)中使用文本表示來(lái)指定非表格布局蝌焚。
layout <- "
AAB
C#B
CDD
"
p1 + p2 + p3 + p4 + plot_layout(design = layout)
正如在最后幾幅圖中顯示的那樣裹唆,圖形之間的圖例就變得多余。雖然可以在組裝之前刪除某個(gè)圖中的所有圖例之外的所有圖例只洒,但patckwork
為常見(jiàn)情況提供了一些更容易的方法:
p1 + p2 + p3 + plot_layout(ncol = 2, guides = "collect")
選擇收集guides
將把所有圖例放在一起许帐,放在全局主題所支配的位置。此外毕谴,它將刪除任何重復(fù)的圖例成畦,只在圖形中留下唯一的圖例距芬。重復(fù)檢測(cè)圖例的外觀,而不是它來(lái)自的底層比例羡鸥。因此蔑穴,它只會(huì)刪除完全相同的圖例。如果您想通過(guò)將參考線放置在布局的空白區(qū)域來(lái)優(yōu)化空間使用惧浴,您可以為收集的參考線指定一個(gè)繪圖區(qū)域:
p1 + p2 + p3 + guide_area() + plot_layout(ncol = 2, guides = "collect")
9.1.2 修改子圖
patchwork執(zhí)行規(guī)則是:在渲染之前存和,繪圖保持為標(biāo)準(zhǔn)的 ggplot 對(duì)象。這意味著它們?cè)诮M裝后可以進(jìn)行修改衷旅【柰龋可以通過(guò)[[]]
索引檢索和設(shè)置特定圖:
p12 <- p1 + p2
p12[[2]] <- p12[[2]] + theme_light()
p12
但是,通常有必要一次修改所有子圖柿顶,例如給它們一個(gè)共同的主題茄袖。patchwork提供了的&
適用于該處:
p1 + p4 & theme_minimal()
如果它們?cè)谠撦S上具有相同的圖形屬性,這也可用于為繪圖提供一個(gè)公共軸:
p1 + p4 & scale_y_continuous(limits = c(0, 45))
9.1.3 添加注釋
圖形一旦被組裝起來(lái)嘁锯,它們就開(kāi)始形成一個(gè)整體宪祥。這也意味著標(biāo)題、副標(biāo)題和說(shuō)明文字通常與整個(gè)圖形有關(guān)家乘,而不再是其中的某一個(gè)圖形蝗羊。可以使用該plot_annotation()函數(shù)將標(biāo)題等添加到組裝的圖中仁锯。
p34 <- p3 + p4 + plot_annotation(
title = "A closer look at the effect of drive train in cars",
caption = "Source: mpg dataset in ggplot2"
)
p34
根據(jù)調(diào)用plot_annotation()中的主題規(guī)范格式化標(biāo)題耀找。
p34 + plot_annotation(theme = theme_gray(base_family = "mono"))
由于全局主題通常跟隨子圖形的主題,&
與主題對(duì)象一起使用將修改全局主題以及子圖形的主題
p34 & theme_gray(base_family = "mono")
另一種類型的注釋业崖,特別是在文獻(xiàn)中野芒,是向每個(gè)子圖添加標(biāo)簽,然后用于在文本和標(biāo)題中識(shí)別它們双炕。ggplot2 正好有這個(gè)tag
元素狞悲,patchwork 提供了使用tag_levels
參數(shù)自動(dòng)設(shè)置它的功能。它可以自動(dòng)生成拉丁字符妇斤、阿拉伯?dāng)?shù)字或羅馬數(shù)字效诅。
p123 <- p1 | (p2 / p3)
p123 + plot_annotation(tag_levels = "I") # Uppercase roman numerics
一個(gè)附加功能是可以使用嵌套來(lái)定義新的標(biāo)記級(jí)別:
p123[[2]] <- p123[[2]] + plot_layout(tag_level = "new")
p123 + plot_annotation(tag_levels = c("I", "a"))
可以看出,patchwork可以生成不同的圖形排布趟济,并且 API 會(huì)隨著組件的復(fù)雜程度而擴(kuò)展,從簡(jiǎn)單+
地將多個(gè)繪圖放置在同一區(qū)域咽笼,到使用嵌套顷编、布局、和注釋以創(chuàng)建高級(jí)自定義布局剑刑。
9.2 在圖形上排列圖
雖然 patchwork 中的許多功能都與對(duì)齊網(wǎng)格中的圖有關(guān)媳纬,但它也允許您制作插圖双肤,即放置在另一個(gè)圖上的小圖。此功能包含在inset_element()函數(shù)中钮惠,該函數(shù)用于將給定的繪圖標(biāo)記為要放置在前一個(gè)繪圖上的插圖茅糜,并記錄所需的位置等∷赝欤基本用法如下:
p1 + inset_element(p2, left = 0.5, bottom = 0.4, right = 0.9, top = 0.95)
實(shí)際位置由給定插圖的左側(cè)蔑赘、右側(cè)、頂部和底部位置指定预明。默認(rèn)值是npc
缩赛,在給定區(qū)域中使用從 0 到 1 的單位,但grid::unit()可以明確給出它們來(lái)使用任何單位撰糠。該位置默認(rèn)設(shè)置為面板區(qū)域酥馍,但這可以通過(guò)align_to
參數(shù)進(jìn)行更改。結(jié)合這些知識(shí)點(diǎn)阅酪,我們可以在距右上角 15 毫米處放置一個(gè)插圖旨袒,如下所示:
p1 +
inset_element(
p2,
left = 0.4,
bottom = 0.4,
right = unit(1, "npc") - unit(15, "mm"),
top = unit(1, "npc") - unit(15, "mm"),
align_to = "full"
)
插圖不限于 ggplots。wrap_elements()可以使用任何支持的圖形术辐,包括patchwork拼湊圖:
p24 <- p2 / p4 + plot_layout(guides = "collect")
p1 + inset_element(p24, left = 0.5, bottom = 0.05, right = 0.95, top = 0.9)
插圖的一個(gè)很好的特點(diǎn)是它們?cè)诒讳秩局氨憩F(xiàn)為標(biāo)準(zhǔn)的拼湊子圖砚尽。這意味著它們可以在組裝后進(jìn)行修改,通過(guò)使用&
:
p12 <- p1 + inset_element(p2, left = 0.5, bottom = 0.5, right = 0.9, top = 0.95)
p12 & theme_bw()
自動(dòng)標(biāo)記也按預(yù)期工作:
p12 + plot_annotation(tag_levels = 'A')
9.3 總結(jié)
本章簡(jiǎn)要概述了 patchwork 提供的一些組合可能性术吗。Patchwork 不僅支持 ggplots尉辑,還允許您在需要時(shí)將網(wǎng)格和基本圖形元素與您的繪圖結(jié)合起來(lái)。它還允許使用area()構(gòu)造函數(shù)较屿,而不僅僅是此處展示的文本表示進(jìn)行更復(fù)雜的設(shè)計(jì)隧魄。所有這些功能以及更多功能都包含在其網(wǎng)站上的不同指南中: https://patchwork.data-imaginist.com