寫在前面
後天就要回學校了,有點捨不得,捨不得家裡2米的大床,捨不得我安靜的書房,捨不得我專屬的健身空間,捨不得一下樓就能吃到媽媽做的飯菜,捨不得老爸每周給我送水果熬的雞湯鴿子湯,當然也捨不得家鄉的朋友們。
其實,還有一個捨不得的,就是家中的這一平方米。
在家的7個多月時間裡,有1/2的時間都是在這一平米度過,在這裡處理了數據,完成了我真正意義上的第一篇英文paper和第一篇中文小論文,也自學了許多有趣的知識,寫了幾篇閱讀量還可以的推送。
所以,想在今天,臨出發前,和大家,再分享一個有趣、簡單但非常實用的小知識,我相信科研小白以及已經上路的研究生博士生們都會用到的。
畢竟回北京以後,我可能就又恢復到foodie美食博主的身份啦!
關於「繪圖拼接」
「繪圖拼接」,字面上的意思就是,把畫好的一堆圖,按照你想要的樣式、結構,拼起來,成為一個大的、有更多信息和內容的圖。
可能只是兩個圖簡單的橫向、縱向拼接。
也可能是多個類似主題圖的拼接,且共用了一個legend。
也可能是兩個複雜的圖的拼接,每個複雜的圖片裡面還含有更多子圖,reveal更多不同的信息。
那為何要掌握「繪圖拼接」呢?因為大多數的期刊,在投稿的時候,都會在投稿須知裡面說到,圖片數量不允許超過多少多少,有的說不許超過5個,有的不許超過6個,也有可能是4個!
所以,如果把這些子圖都分散開,那可能一個主題的圖,就要佔用4-6個圖片數量了,無法表達論文的全部內容。
當然,也有人說,那就分開自己拼唄,Word裡面手動拼!
是的,我曾經···也是這麼幹的··· 但是這個做法,實際上非常的不方便,每次調整圖的時候都要手動調節位置就算了,關鍵有時間真的做不到「整整齊齊」!其實你們可以看到我的(b)和(d)圖是有點歪的。
所以,如果以後想有進步,寫出更好的論文,投更好的期刊,這種「手動拼接」做法是不建議的!
那如何解放雙手,更簡單的實現拼接呢?
先說說R中的par()和customLayout
其實之前,我也是用R寫代碼拼圖的,但是只會簡單的par(),比如par(mfrow(2,2)),創建一個2*2的畫布,然後分別畫四個子圖。但是我發現,這種方法畫的圖①是不太美觀②拼接的也不太智能(也可能我沒深入挖掘這個方法),雖然它很實用,可以完美拼接R中的base繪圖對象,但是我後來還是慢慢拋棄了他。
當然,customLayout也不錯,聽名字就知道很「自定義」和「為所欲為」,可以拼接base繪圖對象也可以拼接ggplot2繪圖對象。比如:
先創建一個叫lay1的畫布,裡面有四個子圖空間(我這裡沒畫具體的子圖),寬比例是3:2(左:右),高比例是2:1(上:下)。
然後創建一個叫lay2的畫布,同樣是四個子空間,但是寬比例是3:5(左:右),高比例是2:4(上:下)。
然後就可以通過lay_bind_col()或者lay_bind_row()進行按列或者按行的拼接啦,比如我這裡按列拼接兩個畫布。並且指定了lay1寬度是lay2寬度的三倍。
所以大家可以使用customLayout包盡情的customize!
學會用R中的cowplot和patchwork包
前面嘰嘰喳喳半天,終於到了本推送的核心內容了,其實我最想介紹的是cowplot和patchwork這兩個包。
為何說這兩個包呢?因為他的拼接思路更符合我們人腦畫畫的思路,step by step,且和ggplot2包的結合特別好。而ggplot2是R中最強大的繪圖包,也是我最常用的,所以,我決定向大家推薦這二者!
首先要注意一下,cowplot包是可以直接install的,但是patchwork是要在github中加載的。如圖所示。
把這兩個包安裝完之後,就可以進行拼接了。由於本推送的重點在「拼接」,而非「畫圖」,所以不會具體解釋畫圖步驟,並且使用的也都是ggplot2中最常見的畫圖語法。
下面所有圖的例子都來自R中內置資料庫iris, mtcars和diamonds。
使用cowplot包進行拼接
大家可以發現,我們可以利用cowplot中的plot_grid()進行拼接,上下兩幅圖同樣是縱向拼接,但是上面的圖p5就拼接得整整齊齊,而下面圖的Y軸並沒有對齊。原因就是下面的圖p6沒有設置align="v",這裡的「v」是vertical的意思。所以如果是水平對齊,就要設置align="h",以保證X軸水平對齊。
同樣地,如果我想給拼接的兩個圖,添加標籤,以及設置相對寬度,高度呢?
這裡我做了水平拼接,設置了相對寬度是1:2,給兩個圖加了「A」和「B」標籤。
是不是很方便很簡單???
那如果有三個圖呢?或者更多的圖呢?
我們可以採取一個plot_grid()嵌套的方式來完成,比如下面這個圖,我先plot_grid()對p7和p8完成拼接,並標記為「B」和「C」,然後再用這一個整體和p9進行拼接。
當然,我們還有一個畫圖思路,同樣可以實現上面這個圖的拼接,只不過是通過ggdraw()來完成的,而不是plot_grid()。
通過代碼可以發現,這和我們小時候畫畫的思路是完全一樣的!!!
先把p10和p11拼接起來,兩個圖的相對寬度是1:2,拼起來的圖叫做p12。
然後開始拼接,先畫一個空圖ggdraw(),然後畫圖p9,後面四個數字x,y,z,w分別表示p9原點的相對坐標,和長寬佔比,同理開始畫p12,然後給p9和p12標籤,並說明標籤的位置和顏色。拼接出來如圖所示。
當然,你也可以三個分別直接畫上去,進行拼接。和上面對比一下代碼、圖,有沒有看出啥區別!
當然,有人會說,有沒有嵌套的拼接呢?
有的呀!
仔細看,這裡是先ggdraw(p7),也就是說,先畫好p7,然後後面的draw_plot(p8)的一系列操作就都是在p7畫圖基礎上去完成啦!這樣就實現了嵌套!
我相信有人會問,如何共用一個legend呢?
這裡就有一個get_legend()的操作,也就是說我先保留了p10的圖例,去掉了p11的圖例,即theme(legend.position="none"),然後我獲取p10的圖例,然後通過plot_grid()對去掉圖例的p10和本身沒有圖例的p11進行拼接,最後再進行一個複合拼接,將他們與圖例拼在一起。
(下圖只是一個我隨便做的例子,圖例對不上,重點看代碼)
簡單聊聊patchwork
其實能會使用cowplot()基本就可以完成我們正常的科研繪圖和拼接工作了,但是為啥要聊聊patchwork呢?因為他的語法實在是太簡單!太直觀!太可愛啦!
它的表達方式有很多種,比如:加減乘除,比如交集併集,比如花括號,但是其拼接思路就和我們做加減乘除一樣簡單!
該圖是由第一行代碼畫出來的
((p10+p11)+p7+p8+plot_layout(ncol=2))
大家可以自已試試其他兩行代碼,畫出來有什麼區別呢?自己動手加強理解!
至於最後圖片的導出問題,比如如何導出高質量的圖片,對dpi進行調整,請參考我之前寫的「科研小白可能會遇到的期刊圖片導出問題」。
寫在最後
終於完成了在家的最後一篇推送,個人認為寫的過程還是很開心、充實的,因為寫推送與我而言,是愛好,也是利用輸出方式鞏固知識的一種方式。
為了寫這篇推送我也把這些代碼重複寫了很多次,加深了理解,所以說practice makes perfect,希望能夠對大家有所幫助吧!!!
歡迎大家閱讀、轉發、打賞、點讚一條龍呀~