前言

上一節講的是如何使用

cowplot

包來對圖形進行排列對齊,今天要講的是,如何使用

patchwork

包來排列圖形

patchwork

包主要針對的是

ggplot2

圖形,也可以是其他影象系統繪製的圖形。

patchwork

以一種簡單的方式對圖形進行排列和組合,不論多複雜的組合圖形,都能確保圖形之間正確對齊

安裝

patchwork

install。packages(“patchwork”)

匯入相關模組

library(ggplot2)

library(patchwork)

示例

我們主要使用如下圖形進行說明

p1 <- ggplot(mtcars) +

geom_point(aes(mpg, disp), colour = “#7fc97f”) +

ggtitle(‘Plot 1’)

p2 <- ggplot(mtcars) +

geom_boxplot(aes(gear, disp, fill = factor(gear)),

show。legend = FALSE) +

ggtitle(‘Plot 2’)

p3 <- ggplot(mtcars) +

geom_point(aes(hp, wt, colour = mpg)) +

scale_colour_gradientn(

colours = c(“#66c2a5”, “#fc8d62”, “#8da0cb”)) +

ggtitle(‘Plot 3’)

p4 <- ggplot(mtcars) +

geom_bar(aes(gear, fill = factor(gear)),

show。legend = FALSE) +

facet_wrap(~cyl) +

ggtitle(‘Plot 4’)

1. 組合圖形

1.1 新增圖形

patchwork

使用

+

來連線兩個圖形

p1 + p2

R 資料視覺化 —— 圖形排列之 patchwork

拼湊多個圖

patch <- p1 + p2

p3 + patch

R 資料視覺化 —— 圖形排列之 patchwork

1.1.1 新增非 ggplot 圖形

有時候,你可能想要新增其他型別的圖片,例如,

grid

系統的圖形物件

p1 + grid::textGrob(‘Some really important text’)

R 資料視覺化 —— 圖形排列之 patchwork

或者,

gridExtra

tableGrob

p1 + gridExtra::tableGrob(mtcars[1:10, c(‘mpg’, ‘disp’)])

R 資料視覺化 —— 圖形排列之 patchwork

此外,對於

base

繪圖系統,可以透過單邊公式的方式來新增

p1 + ~plot(mtcars$mpg, mtcars$disp, main = ‘Plot 2’,

col = if_else(mtcars$disp > 250, “red”, “green”))

R 資料視覺化 —— 圖形排列之 patchwork

我們可以看到,兩幅圖並沒有對齊,要將

ggplot

圖形和非

ggplot

圖形對齊,需要使用

par()

函式來進行調整

ggplot

圖形可以使用

wrap_elements()

函式來新增,可以進行更加靈活的控制,例如

old_par <- par(mar = c(0, 2, 0, 0), bg = NA)

p1 + wrap_elements(panel = ~plot(mtcars$mpg, mtcars$disp), clip = FALSE)

par(old_par)

如果你想將非

ggplot

圖放在最前面,例如

> grid::textGrob(‘Text on left side’) + p1

NULL

返回的是

NULL

,這時,也需要使用

wrap_elements()

函式

wrap_elements(grid::textGrob(‘Text on left side’)) + p1

R 資料視覺化 —— 圖形排列之 patchwork

總的來說,對齊方式比

cowplot

更加複雜和繁瑣

1.1.2 堆疊和包裝

+

運算子只能簡單地對圖形進行組合,並不能提供任何佈局資訊,圖片是以堆疊還是並列的方式排列。

因此,

patchwork

提供了兩個運算子:

|

:圖形並列放置,即按行

/

:圖形豎直堆疊,即按列

例如

p1 | p2

R 資料視覺化 —— 圖形排列之 patchwork

p1 / p2

R 資料視覺化 —— 圖形排列之 patchwork

這三個運算子的運算順序與數學上一致,

/

|

+

優先順序更高,最好的方式是使用小括號來區分組合優先順序,例如

p1 / (p2 | p3)

R 資料視覺化 —— 圖形排列之 patchwork

1.1.3 組合函式

當我們需要處理繪圖函式列表時,使用

+

來新增圖形會顯得很笨拙,

wrap_plots()

允許傳入一個繪圖列表,或者每個繪圖以引數的形式分開傳遞

wrap_plots(p1, p2, p3, p4)

# 或者

wrap_plots(list(p1, p2, p3, p4))

R 資料視覺化 —— 圖形排列之 patchwork

1.2 左側巢狀

上面的運算子都是將圖形新增到左側,例如

patch <- p1 + p2

p3 + patch

R 資料視覺化 —— 圖形排列之 patchwork

我們改變新增的順序,圖形會看起來不太一樣

patch + p3

R 資料視覺化 —— 圖形排列之 patchwork

這兩種方式有什麼不一樣呢?因為

+

是按順序逐個新增的,

+

的右側圖形需要與前面連線的圖形串內的圖形處於同一個巢狀級別。

對於

patch + p3

,相當於是

p1 + p2 + p3

,而對於

p3 + patch

patch

p3

處於同一巢狀級別

patchwork

還提供了一個

-

運算子來處理這種情況,其作為連線符而不是減號,兩邊的圖形處於同一巢狀級別

patch - p3

R 資料視覺化 —— 圖形排列之 patchwork

或者使用

wrap_plots()

,所有輸入引數都處於同一級別

wrap_plots(patch, p3)

1.3 修改圖形

在我們建立一個

patchwork

時,會返回最後一個新增的圖形物件,我們可以繼續新增

ggplot

圖形物件

p1 + p2 + geom_jitter(aes(gear, disp))

R 資料視覺化 —— 圖形排列之 patchwork

如果想要修改其他圖形,可以使用雙中括號加索引的方式訪問

patchwork <- p1 + p2

patchwork[[1]] <- patchwork[[1]] + theme_minimal()

patchwork

R 資料視覺化 —— 圖形排列之 patchwork

修改全部

有時,我們可能想對所有圖形進行統一的修改,例如修改主題,

patchwork

提供了兩個運算子

&

:為所有子圖新增元素

*

:為當前巢狀級別的所有子圖新增元素

patchwork <- p3 / (p1 | p2)

patchwork & theme_minimal()

R 資料視覺化 —— 圖形排列之 patchwork

patchwork * theme_minimal()

R 資料視覺化 —— 圖形排列之 patchwork

2. 控制佈局

雖然使用

+

|

/

運算子可以建立複雜的圖形,但是還缺少一些更靈活的控制,下面我們介紹如何使用

plot_layout()

函式來進行更多的控制

2.1 新增空白佔位

plot_spacer()

函式可以新增一個空白的區域,大小與同一巢狀級別的圖形一樣

p1 + plot_spacer() + p2 + plot_spacer() + p3 + plot_spacer()

R 資料視覺化 —— 圖形排列之 patchwork

不同的巢狀級別的佔位大小不同

(p1 + plot_spacer() + p2) / (plot_spacer() + p3 + plot_spacer())

R 資料視覺化 —— 圖形排列之 patchwork

2.2 網格佈局

如果沒有給出任何佈局資訊,會盡可能將圖形按照正方形網格進行排列,如果無法排列,則會使用啟發式的方法自動調整。

我們可以使用

plot_layout()

來控制行列數量,每個網格具有相同的大小

p1 + p2 + p3 + p4 +

plot_layout(ncol = 3)

R 資料視覺化 —— 圖形排列之 patchwork

使用

widths

可以控制相對寬度比

p1 + p2 + p3 + p4 +

plot_layout(widths = c(2, 1))

R 資料視覺化 —— 圖形排列之 patchwork

或者使用絕對大小,使用

heights

設定第一行高度為

5cm

,第二行為剩下的區域

p1 + p2 + p3 + p4 +

plot_layout(widths = c(2, 1), heights = unit(c(5, 1), c(‘cm’, ‘null’)))

R 資料視覺化 —— 圖形排列之 patchwork

2.3 非網格佈局

對於非網格佈局,你可能會想到使用巢狀的方式,但是這樣容易讓不同巢狀級別的圖形很難再對齊。另一種方式是,透過設計自定義佈局來排列圖形。

有兩種自定義佈局的方式,最簡單的就是使用文字表示,例如

layout <- “

##BBBB

AACCDD

##CCDD

p1 + p2 + p3 + p4 +

plot_layout(design = layout)

R 資料視覺化 —— 圖形排列之 patchwork

#

來表示空白區域,

A-D

會根據新增的順序自動對應到圖形,也可以使用數字的方式

layout <- “

##2222

113344

##3344

一種更具程式設計性的方法是使用

area()

函式來構建佈局

layout <- c(

area(t = 2, l = 1, b = 5, r = 4),

area(t = 1, l = 3, b = 3, r = 5)

p1 + p2 +

plot_layout(design = layout)

R 資料視覺化 —— 圖形排列之 patchwork

t

l

b

r

分別指定了圖形所佔的上、左、下、右的網格,例如

layout <- c(

area(1, 1),

area(1, 3, 3),

area(3, 1, 3, 2)

plot(layout)

R 資料視覺化 —— 圖形排列之 patchwork

也可以使用

wrap_plots()

函式來繪製,如果使用文字表示的佈局,可以傳遞命名圖形的方式

layout <- ‘

A#B

D#E

wrap_plots(D = p1, C = p2, B = p3, design = layout)

R 資料視覺化 —— 圖形排列之 patchwork

2.4 固定縱橫比圖

當我們對具有固定縱橫比的圖圖形(如

coord_fixed()

coord_polar()

coord_sf()

建立的圖形)進行組合時,由於

widths

heights

引數值預設設定為

NA

,自動調整圖形的大小看起來會比較奇怪

p_fixed <- ggplot(mtcars) +

geom_point(aes(hp, disp)) +

ggtitle(‘Plot F’) +

coord_fixed()

p_fixed + p1 + p2 + p3

R 資料視覺化 —— 圖形排列之 patchwork

我們可以為

widths

設定值

p_fixed + p1 + p2 + p3 + plot_layout(widths = 1)

R 資料視覺化 —— 圖形排列之 patchwork

雖然其他圖片對齊的很好,但是固定縱橫比的圖片,為了維持大小比例,在某一方向上不再對齊了

2.5 嵌入圖形

前面的例子中,我們使用

area()

函式在網格佈局中將一個圖形嵌入到另一個圖形中,還可以使用

inset_element()

函式將一個圖形或圖形物件嵌入到前一個圖形中,你可以將它放在前一個圖形區域的任何位置。

例如

p1 + inset_element(p2, left = 0。6, bottom = 0。6, right = 1, top = 1)

R 資料視覺化 —— 圖形排列之 patchwork

p1 + inset_element(p2, left = 0, bottom = 0。6, right = 0。4, top = 1, align_to = ‘full’)

R 資料視覺化 —— 圖形排列之 patchwork

預設定位使用的數值的單位為

npc

,我們可以調整

1cm

的位置

p1 + inset_element(

p2,

left = 0。5,

bottom = 0。5,

right = unit(1, ‘npc’) - unit(1, ‘cm’),

top = unit(1, ‘npc’) - unit(1, ‘cm’)

R 資料視覺化 —— 圖形排列之 patchwork

2.6 控制圖例

通常,每幅圖及其圖例都是一個整體,我們可以使用

guides

引數來控制圖例的顯示方式,可選的值為

auto

:如果巢狀的上層嘗試收集圖例,則也會進行收集,否則,放置在圖形邊上

collect

:會將制定巢狀級別的圖例收集起來,並刪除重複的圖例。還可以是

keep

keep

:將圖例放置在對應的圖形邊上

例如

p1 + p2 + p3 + p4 +

plot_layout(guides = ‘collect’)

R 資料視覺化 —— 圖形排列之 patchwork

((p2 / p3 + plot_layout(guides = ‘keep’)) | p1) + plot_layout(guides = ‘collect’)

R 資料視覺化 —— 圖形排列之 patchwork

對於存在重複圖例的組合圖形,我們可能想要刪除其中某一個,例如,對於如下圖形

p1a <- ggplot(mtcars) +

geom_point(aes(mpg, disp, colour = mpg, size = wt)) +

scale_colour_gradientn(colours = c(“#66c2a5”, “#fc8d62”, “#8da0cb”)) +

ggtitle(‘Plot 1a’)

p1a | (p2 / p3)

R 資料視覺化 —— 圖形排列之 patchwork

設定

guides = ‘collect’

(p1a | (p2 / p3)) + plot_layout(guides = ‘collect’)

R 資料視覺化 —— 圖形排列之 patchwork

我們還可以使用

guide_area()

來新增圖例區域,其表現方式基本與

plot_spacer()

一樣,如果沒有設定

collect

形式,則與

plot_spacer()

一樣,如果設定了,則會將所有圖例繪製在該區域

p1 + p2 + p3 + guide_area() +

plot_layout(guides = ‘collect’)

R 資料視覺化 —— 圖形排列之 patchwork

3. 添加註釋和樣式

在組合完圖形之後,通常也需要新增一些註釋資訊,像標題或其他文字註釋。

patchword

提供了

plot_annotation()

函式用於添加註釋

patchwork <- (p1 + p2) / p3

patchwork + plot_annotation(

title = ‘The surprising truth about mtcars’,

subtitle = ‘These 3 plots will reveal yet-untold secrets about our beloved data-set’,

caption = ‘Disclaimer: None of these plots are insightful’

R 資料視覺化 —— 圖形排列之 patchwork

tag_level

引數用於控制標籤的格式,格式包括:

1

:阿拉伯數字

a

:小寫字母

A

:大寫字母

i

:小寫羅馬數字

I

:大寫羅馬數字

patchwork + plot_annotation(tag_levels = ‘A’)

R 資料視覺化 —— 圖形排列之 patchwork

可以使用

theme()

函式來設定標籤的樣式

patchwork +

plot_annotation(tag_levels = ‘A’) &

theme(plot。tag = element_text(size = 8))

R 資料視覺化 —— 圖形排列之 patchwork

如果組合圖形是巢狀佈局,則會遞迴的新增圖形標籤,可以設定多個標籤樣式

patchwork[[1]] <- patchwork[[1]] + plot_layout(tag_level = ‘new’)

patchwork + plot_annotation(tag_levels = c(‘A’, ‘1’))

R 資料視覺化 —— 圖形排列之 patchwork

還可以設定標籤的分隔符、字首和字尾

patchwork + plot_annotation(

tag_levels = c(‘A’, ‘1’),

tag_prefix = ‘Fig。 ’,

tag_sep = ‘。’,

tag_suffix = ‘:’

R 資料視覺化 —— 圖形排列之 patchwork

patchwork + plot_annotation(

tag_levels = c(‘A’, ‘1’),

tag_prefix = ‘Fig。 ’,

tag_sep = ‘。’,

tag_suffix = ‘:’

) & theme(plot。tag。position = c(0, 1),

plot。tag = element_text(size = 8, hjust = 0, vjust = 0)

R 資料視覺化 —— 圖形排列之 patchwork

可以為標籤設定序列,如果設定的序列不夠,後面的圖形標籤會設定為空

patchwork +

plot_annotation(tag_levels = list(c(‘#’, ‘%’), ‘1’))

R 資料視覺化 —— 圖形排列之 patchwork

其他樣式都可以使用

theme()

函式來設定,比如,文字字型

patchwork +

plot_annotation(title = ‘The surprising truth about mtcars’,

theme = theme(plot。title = element_text(size = 18))) &

theme(text = element_text(‘mono’))

R 資料視覺化 —— 圖形排列之 patchwork

- END -