PCA、RDA等排序圖的ggplot2二維視覺化示例

R包ggplot2繪製二維排序圖
前文已分享了PCACADCAPCoANMDSRDAdb-RDACAP)、CCA等排序方法在R語言中的計算過程。對於排序圖的繪製,用於計算的R包中一般會提供視覺化函式,如vegan包的ordiplot()plot.cca()等,ade4scatter()等,便於我們在計算後快速觀測資料特徵。如果有必要,之後可再細調一些引數,讓排序圖更美觀些。
除了打包好的特定作圖函式外,考慮到排序圖的本質是散點圖,所以更普遍的做圖方法,就是將排序座標匯出,然後用專業的作圖包(如ggplot2)繪製,實現更好的視覺化效果。
在前文簡介這些排序方法的分享中,每篇都對應了1-2例相關的作圖示例,包含內建函式以及ggplot2兩種型別。本篇繼續作些延伸內容,單獨展示一些ggplot2繪製二維排序圖的示例。這些示例對於幫助初步掌握作圖方法應該足夠了,文獻中大多也是ggplot2的風格,其它情況下,參考文獻中的樣式仿著來就可以了。
備註:ggplot2本身的作圖語法本篇不涉及,基礎部分還請自行學習了。
示例檔案、R指令碼等的百度盤連結:
https://pan.baidu.com/s/1KUA5owf4y13y1RJbff-l7g
pca_site.txt”是某PCA分析後,匯出的樣方(物件)排序座標,“pca_var.txt”是變數的座標。
cap_site.txt”是某db-RDACAP)分析後,匯出的樣方(物件)排序座標,“cap_sp.txt”是物種(響應變數)排序座標,“cap_env.txt”是環境變數(解釋變數)的排序座標。
PCA等排序圖的繪製
先以某PCA排序圖為例吧。
library(ggplot2)
#資料

pca_site <- read.delim('pca_site.txt', sep = '\t', stringsAsFactors = FALSE)

pca_site$group_all <- paste(pca_site$group1, pca_site$group2, sep = '_')
pca_var <- read.delim('pca_var.txt', sep = '\t', stringsAsFactors = FALSE)

常規的只展示物件的排序圖,PCA前兩軸,顏色區分分組,這裡假設原分析中前兩軸的貢獻率分別為30%20%(貢獻率由實際的計算獲得)
#常規僅樣方的點圖,單組樣式

p <- ggplot(data = pca_site, aes(x = PC1, y = PC2)) +

theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent'), legend.key = element_rect(fill = 'transparent')) +

labs(x = 'PCA1: 30%', y = 'PCA2: 20%')
p + geom_point(aes(color = group1)) +

scale_color_manual(values = c('red2', 'purple2', 'green3'))

如果存在多分組,可以分別以更多的顏色區分,或者點的形狀等。
#多組可以顏色表示

p + geom_point(aes(color = group_all)) +

scale_color_manual(values = c('red', 'purple', 'green', 'red4', 'purple4', 'green4'), limits = c('A_l', 'B_l', 'C_l', 'A_h', 'B_h', 'C_h'))
#或者使用點的顏色+形狀區分

p + geom_point(aes(color = group1, shape = group2)) +

scale_color_manual(values = c('red2', 'purple2', 'green3'), limits = c('A', 'B', 'C')) +

scale_shape_manual(values = c(17, 15), limits = c('l', 'h'))
#漸變色表示連續數值

p + geom_point(aes(color = group3, shape = group1)) +

scale_shape_manual(values = c(19, 17, 15), limits = c('A', 'B', 'C')) +

scale_color_gradientn(colors = colorRampPalette(c('#C0D857', '#3EB897', '#663490'))(7))

一些背景網格線的常選樣式。
#以上述某樣式繼續為例展示

p <- p + geom_point(aes(color = group1, shape = group2)) +

scale_color_manual(values = c('red2', 'purple2', 'green3'), limits = c('A', 'B', 'C')) +

scale_shape_manual(values = c(17, 15), limits = c('l', 'h'))
#一些常見背景樣式

p + theme(axis.line = element_line(colour = 'black'), panel.background = element_blank())
p + geom_vline(xintercept = 0, color = 'gray', size = 0.5) +

geom_hline(yintercept = 0, color = 'gray', size = 0.5)
p + theme(panel.grid.major = element_line(color = 'gray', size = 0.2))

有時能夠看到直接在原圖中標記物件名稱的。
#新增標籤,常規方法

p + geom_text(aes(label = name, color = group1), size = 3, vjust = 2, show.legend = FALSE)
#防止重疊的新增標籤方法

library(ggrepel)
p + geom_text_repel(aes(label = name, color = group1), size = 3, box.padding = unit(0.5, 'lines'), show.legend = FALSE)
p + geom_label_repel(aes(label = name, color = group1), size = 3, box.padding = unit(0.5, 'lines'), show.legend = FALSE)

這種在圖中,根據樣本新增分組橢圓或者多邊形的樣式,經常能看到。
#新增置信橢圓,注意它不是聚類

p + stat_ellipse(aes(color = group1), level = 0.95, linetype = 2, show.legend = FALSE)
p + stat_ellipse(aes(fill = group1), geom = 'polygon', level = 0.95, alpha = 0.1, show.legend = FALSE) +

scale_fill_manual(values = c('red', 'purple', 'green'))
#“偽聚類”,我也不知道怎麼稱呼,既不是真正的聚類也不是置信區間,僅用於標記分組而已

#這種樣式也經常看到吧

#參考自:https://stackoverflow.com/questions/42575769/how-to-modify-the-backgroup-color-of-label-in-the-multiple-ggproto-using-ggplot2

source('geom_enterotype.r')  #見網盤附件
p + geom_enterotype(aes(fill = group1, color = group1, label = group1), show.legend = FALSE) +

scale_fill_manual(values = c('#ffa6a9', '#e8b4fd', '#c7ffc4'))
#還有分組多邊形這種

library(plyr)
group1_border <- ddply(pca_site, 'group1', function(df) df[chull(df[[2]], df[[3]]), ])
p + geom_polygon(data = group1_border, aes(fill = group1, color = group1), alpha = 0.1, show.legend = FALSE) +

scale_fill_manual(values = c('red', 'purple', 'green'))

圖中額外新增一些識別符號、標籤或者特殊形狀之類的,一般推薦後續用AIPSP圖上去更為方便;如果用程式碼新增的話,以一些文字為例。
#額外新增一些標籤等,例如

p + stat_ellipse(aes(fill = group1), geom = 'polygon', level = 0.95, alpha = 0.1, show.legend = FALSE) +

scale_fill_manual(values = c('red', 'purple', 'green')) +

annotate('text', label = 'A', x = -0.15, y = -0.10, size = 5, color = 'red2') +

annotate('text', label = 'B', x = 0.20, y = 0.09, size = 5, color = 'purple2') +

annotate('text', label = 'C', x = -0.20, y = -0.05, size = 5, color = 'green3') +

annotate('text', label = 'PERMANOVA: P<0.001', x = 0.2, y = 0.14, size = 3)

以上均展示了物件的位置,平常見到的大多數PCA排序圖也只展示了物件;如果期望將變數也呈現出來。
#新增變數,PCA 這種線性模型中,變數常以向量形式展示

p + geom_segment(data = pca_var, aes(x = 0, y = 0, xend = PC1, yend = PC2), arrow = arrow(length = unit(0.1, 'cm')), color = 'blue', size = 0.3) +

geom_text(data = pca_var, aes(x = PC1 * 1.1, y = PC2 * 1.1, label = name), color = 'blue', size = 3)
#CA 這種單峰模型中,變數則常直接展示為點,這裡順便以該示例資料作個展示,假設它是個 CA 的資料

p + geom_text(data = pca_var, aes(x = PC1, y = PC2, label = name), color = 'blue', size = 3) +

labs(x = 'CA1', y = 'CA2')

組合一下上述提到的方法,隨便來一個。
#象徵性來個組合樣式的

p <- ggplot(data = pca_site, aes(x = PC1, y = PC2)) +

geom_point(aes(color = group1, shape = group2)) +

geom_enterotype(aes(fill = group1, color = group1, label = group1), show.legend = FALSE) +

scale_color_manual(values = c('red2', 'purple2', 'green3'), limits = c('A', 'B', 'C')) +

scale_shape_manual(values = c(17, 15), limits = c('l', 'h')) +

scale_fill_manual(values = c('#ffa6a9', '#e8b4fd', '#c7ffc4')) +

guides(color = FALSE) +

theme(panel.grid.major = element_line(color = 'gray', size = 0.2), panel.background = element_rect(color = 'black', fill = 'transparent'), 

        legend.title = element_blank(), legend.key = element_rect(fill = 'transparent'), legend.position = c(0.92, 0.87), legend.background= element_blank()) +

labs(x = 'PCA1: 30%', y = 'PCA2: 20%') +

annotate('text', label = 'PERMANOVA: P<0.001', x = 0.2, y = 0.14, size = 3)
p

以及偶爾也能看到和其它圖形組合在一起的,例如結合箱線圖表示物件的分佈更為直觀。
#在圖的兩側新增箱線圖展示點的分佈

pc1_boxplot <- ggplot(data = pca_site, aes(x = group1, y = PC1)) +

geom_boxplot(aes(color = group1)) +

scale_color_manual(values = c('red2', 'purple2', 'green3'), limits = c('A', 'B', 'C')) +

theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent'), 

        legend.position= 'none', axis.title = element_text(color = 'transparent')) +

coord_flip()
pc2_boxplot <- ggplot(data = pca_site, aes(x = group1, y = PC2)) +

geom_boxplot(aes(color = group1)) +

scale_color_manual(values = c('red2', 'purple2', 'green3'), limits = c('A', 'B', 'C')) +

theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent'), 

        legend.position= 'none', axis.title = element_text(color = 'transparent'))
library(grid)
grid.newpage()

pushViewport(viewport(layout = grid.layout(3, 3)))

print(p, vp = viewport(layout.pos.row = 1:2, layout.pos.col = 1:2))

print(pc1_boxplot, vp = viewport(layout.pos.row = 3, layout.pos.col = 1:2))

print(pc2_boxplot, vp = viewport(layout.pos.row = 1:2, layout.pos.col = 3))
#這裡用了 grid 包實現組合,還有很多 R 包可用於組合,還請自行了解了

#如果覺得對齊效果不太好,在 print() 函數里除錯引數對齊

#或者後面用 AI、PS 調整下更方便

RDA等排序圖的繪製
這裡以某db-RDA(CAP)的計算座標為例吧。
基本的作圖方法上文已作了描述,這裡直接先展示一例只包含樣方和環境變數的雙序圖,假設原分析中前兩個約束軸的解釋率分別為25%15%(約束軸的解釋率由實際的計算獲得)
library(ggplot2)
#資料

cap_site <- read.delim('cap_site.txt', sep = '\t', stringsAsFactors = FALSE)

cap_sp <- read.delim('cap_sp.txt', sep = '\t', stringsAsFactors = FALSE)

cap_env <- read.delim('cap_env.txt', sep = '\t', stringsAsFactors = FALSE)
#作圖,雙序圖

p <- ggplot(data = cap_site, aes(x = CAP1, y = CAP2)) +

geom_point(aes(color = group)) +

stat_ellipse(aes(fill = group), geom = 'polygon', level = 0.95, alpha = 0.1, show.legend = FALSE) +

scale_color_manual(values = c('red2', 'purple2', 'green3'), limits = c('A', 'B', 'C')) +

scale_shape_manual(values = c(17, 15), limits = c('l', 'h')) +

scale_fill_manual(values = c('red', 'purple', 'green')) +

theme(panel.grid = element_blank(), panel.background = element_rect(color = 'black', fill = 'transparent'), 

        legend.title = element_blank(), legend.key = element_rect(fill = 'transparent')) +

geom_vline(xintercept = 0, color = 'gray', size = 0.5) +

geom_hline(yintercept = 0, color = 'gray', size = 0.5) +

geom_segment(data = cap_env, aes(x = 0, y = 0, xend = CAP1, yend = CAP2), arrow = arrow(length = unit(0.2, 'cm')), color = 'blue', size = 0.3) +

geom_text(data = cap_env, aes(x = CAP1 * 1.1, y = CAP2 * 1.1, label = name), color = 'blue', size = 3) +

labs(x = 'CAP1: 25%', y = 'CAP2: 15%')
p

帶樣方、物種和環境變數的三序圖。
#考慮將物種變數加入,展示為三序圖

p + geom_segment(data = cap_sp, aes(x = 0, y = 0, xend = CAP1, yend = CAP2), arrow = arrow(length = unit(0.1, 'cm')), color = 'orange', size = 0.2) +

geom_text(data = cap_sp, aes(x = CAP1 * 1.1, y = CAP2 * 1.1, label = name), color = 'orange', size = 2)
#物種也用顏色區分下分類

#物種數量太多了,這裡選部分物種演示下好了

cap_sp_select <- cap_sp[1:10, ]
p + geom_segment(data = cap_sp_select, aes(x = 0, y = 0, xend = CAP1, yend = CAP2, color = sp_class), 

        arrow = arrow(length = unit(0.1, 'cm')), size = 0.2, show.legend = FALSE) +

geom_text(data = cap_sp_select, aes(x = CAP1 * 1.1, y = CAP2 * 1.1, label = name, color = sp_class), size = 2) +

scale_color_manual(values = c('red2', 'purple2', 'green3', '#8DD3C7', '#BEBADA', '#FB8072', '#80B1D3'), 

        limits = c('A', 'B', 'C', 'pa', 'pb', 'pr', 'a'))
#物種直接以點展示,而非向量

p + geom_point(data = cap_sp_select, aes(x = CAP1, y = CAP2), color = 'orange', size = 1)
p + geom_text(data = cap_sp_select, aes(x = CAP1, y = CAP2, label = name), color = 'orange', size = 2)

連結

相關文章