日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

R語言環(huán)形熱圖繪制(circos圖)

 阿越就是我 2024-05-10 發(fā)布于上海



圓形布局對(duì)于表示復(fù)雜的信息非常有用。首先,它可以用更長(zhǎng)的坐標(biāo)軸或大量的類別表示不同的信息;其次,它可以直觀地展示數(shù)據(jù),將多個(gè)圓環(huán)聚焦于同一對(duì)象;第三,它可以清楚地展示元素之間的關(guān)系。圓形布局提供了一種在圓圈上排列信息的有效方法,而且很漂亮。

Circos是一個(gè)廣泛用于在Perl中實(shí)現(xiàn)的圓形布局的工具。它大大增強(qiáng)了科學(xué)結(jié)果的可視化(特別是在基因組學(xué)領(lǐng)域)。因此,具有圓形布局的圖通常被命名為“circos圖”。

circlize包旨在在R中實(shí)現(xiàn)Circos。在R中實(shí)現(xiàn)的一個(gè)重要優(yōu)勢(shì)是,R是一個(gè)理想的環(huán)境,可在數(shù)據(jù)分析和數(shù)據(jù)可視化之間提供無縫連接。circlize不是為Circos生成配置文件的前端包裝器,而是使用R優(yōu)雅的統(tǒng)計(jì)和圖形引擎,完全以R風(fēng)格編碼。我們的目標(biāo)是保持Circos的靈活性和可配置性,同時(shí)使軟件包更易于使用并增強(qiáng)它以支持更多類型的圖形。

本文目錄:

  • 設(shè)計(jì)原理

  • 快速上手

  • 添加圖形元素的方式

  • 圓形熱圖

設(shè)計(jì)原理

圓形布局由扇區(qū)(sectors)和圓環(huán)(tracks)組成。對(duì)于不同類別的數(shù)據(jù),它們被分配到不同的扇區(qū),對(duì)于同一類別的多個(gè)測(cè)量,它們表示為從外到內(nèi)的堆疊圓環(huán)。扇區(qū)和圓環(huán)的交集部分稱為單元格(cell)(或網(wǎng)格(grid)、面板(panel)),它是圓形布局中的基本單元。它是用于繪制數(shù)據(jù)點(diǎn)的假想繪圖區(qū)域。

由于大多數(shù)圖形都是由簡(jiǎn)單的圖形組成的,如點(diǎn)、線、多邊形等,Circlize實(shí)現(xiàn)了在圓形繪圖區(qū)域添加低級(jí)圖形的功能,因此可以通過不同組合的低級(jí)圖形功能輕松生成更復(fù)雜的圖形。這一原則確保了高級(jí)圖形的類型不受軟件本身的限制,并且可以使用其他高級(jí)圖形R包在其上構(gòu)建特定的高級(jí)圖形。

目前,有以下可用于添加低級(jí)圖形的函數(shù)。用法與沒有circos.前綴的函數(shù)非常相似,除了一些專門為圓形可視化設(shè)計(jì)的增強(qiáng)功能。

  • circos.points():在單元格中添加點(diǎn)。
  • circos.lines():在單元格中添加線。
  • circos.segments():在單元格中添加線段。
  • circos.rect():在單元格中添加矩形。
  • circos.polygon():在單元格中添加多邊形。
  • circos.text():在單元格中添加文本。
  • circos.axis()circos.yaxis():在單元格中添加坐標(biāo)軸。

以下函數(shù)在圓圈中的兩個(gè)圓環(huán)之間繪制鏈接:

  • circos.link()

以下函數(shù)繪制高級(jí)圖形:

  • circos.barplot():繪制條形圖。
  • circos.boxplot():繪制箱線圖。
  • circos.violin():繪制小提琴圖。
  • circus.heatmap():繪制圓形熱圖。
  • circos.raster():繪制光柵圖像。
  • circuses.arrow():繪制圓形箭頭。

以下功能排列圓形布局。

  • circos.initialize():在圓圈上分配扇區(qū)。
  • circos.track():為單個(gè)圓環(huán)中的單元格創(chuàng)建繪圖區(qū)域。
  • circos.update():更新現(xiàn)有的單元格。
  • circos.par():圖形參數(shù)。
  • circos.info():打印當(dāng)前圓形圖的一般參數(shù)。
  • circos.clear():重置圖形參數(shù)和內(nèi)部變量。

快速上手

在我們深入探討細(xì)節(jié)之前,我首先演示一個(gè)簡(jiǎn)單的例子,使用circlize包中的基本功能來幫助你了解該包的工作原理。

首先是生成演示數(shù)據(jù),一個(gè)字符型向量表示類別,另外兩個(gè)變量是數(shù)值型:

set.seed(999)
n <- 1000
df <- data.frame(sectors = sample(letters[1:8], n, replace = TRUE),
                x = rnorm(n), 
                y = runif(n)
                )
head(df)
  sectors           x         y
1 c -0.33837650 0.2277292
2 d 0.20128773 0.8345422
3 e 0.60271173 0.6507941
4 g -0.22501815 0.8613092
5 a -0.01011359 0.3624672
6 f -0.19359724 0.5251656

使用circlize的第一步是初始化圓形布局。函數(shù)會(huì)自動(dòng)根據(jù)X軸的范圍和類別變量將圓形劃分為不同的扇區(qū)(相當(dāng)于自動(dòng)分配x軸范圍):

library(circlize)

circos.par("track.height" = 0.1# 設(shè)置圓環(huán)的高度為0.1,也就是圓形半徑的10%
circos.initialize(df$sectors, x = df$x)

運(yùn)行以上代碼后不會(huì)顯示任何圖形,因?yàn)榇藭r(shí)只是進(jìn)行了初始化,并沒有開始畫圖~

接下來如果要畫圖的話首先要使用circos.track添加圓環(huán),然后使用各種低級(jí)繪圖函數(shù)添加各種圖形元素,比如點(diǎn)、線、文字等:

# 初始化布局
circos.par("track.height" = 0.1# 設(shè)置圓環(huán)的高度為0.1,也就是圓形半徑的10%
circos.initialize(df$sectors, x = df$x)

# 添加第一個(gè)圓環(huán)
circos.track(df$sectors, y = df$y, # 這里相當(dāng)于自動(dòng)分配y軸范圍
    panel.fun = function(x, y) { # 定義添加點(diǎn)和文字的細(xì)節(jié),你可以去掉這個(gè)函數(shù)試試看
        circos.text(CELL_META$xcenter, 
            CELL_META$cell.ylim[2] + mm_y(5), 
            CELL_META$sector.index)
        circos.axis(labels.cex = 0.6)
        }
    )
col = rep(c("#FF0000""#00FF00"), 4)

# 添加點(diǎn)
circos.trackPoints(df$sectors, df$x, df$y, col = col, pch = 16, cex = 0.5)
# 在指定panel添加文字
circos.text(-10.5"text", sector.index = "a", track.index = 1)

上面這個(gè)原圓環(huán)圖有8個(gè)單元格(或者叫8個(gè)panel)。

為了更直觀的展示這個(gè)繪圖過程,你可以先運(yùn)行前3行看看結(jié)果,然后再運(yùn)行第4和第5行,再運(yùn)行第6行。其實(shí)這個(gè)過程就是R的繪圖過程,關(guān)于這方面的細(xì)節(jié),大家感興趣的可以參考書籍:《R繪圖系統(tǒng)》。

panel.fun是一個(gè)用于控制單元格細(xì)節(jié)的函數(shù),后面會(huì)詳細(xì)介紹。CELL_META$xxx是一個(gè)快捷函數(shù),可以幫你提取橫縱坐標(biāo)等信息。

接下來你可以繼續(xù)添加更多的圓環(huán)

# 初始化布局
circos.par("track.height" = 0.1# 設(shè)置圓環(huán)的高度為0.1,也就是圓形半徑的10%
circos.initialize(df$sectors, x = df$x)

# 添加第一個(gè)圓環(huán)
circos.track(df$sectors, y = df$y, # 這里相當(dāng)于自動(dòng)分配y軸范圍
    panel.fun = function(x, y) { # 定義添加點(diǎn)和文字的細(xì)節(jié),你可以去掉這個(gè)函數(shù)試試看
        circos.text(CELL_META$xcenter, 
            CELL_META$cell.ylim[2] + mm_y(5), 
            CELL_META$sector.index)
        circos.axis(labels.cex = 0.6)
        }
    )


col = rep(c("#FF0000""#00FF00"), 4)

# 添加點(diǎn)
circos.trackPoints(df$sectors, df$x, df$y, col = col, pch = 16, cex = 0.5)
# 添加文字
circos.text(-10.5"text", sector.index = "a", track.index = 1)

# 添加第2個(gè)圓環(huán)
bgcol = rep(c("#EFEFEF""#CCCCCC"), 4)
circos.trackHist(df$sectors, df$x, bin.size = 0.2, bg.col = bgcol, col = NA)

接下來載添加第3個(gè)圓環(huán)。我們隨機(jī)從每個(gè)單元格中挑選10個(gè)點(diǎn),然后用線條連接起來

# 初始化布局
circos.par("track.height" = 0.1# 設(shè)置圓環(huán)的高度為0.1,也就是圓形半徑的10%
circos.initialize(df$sectors, x = df$x)

# 添加第一個(gè)圓環(huán)
circos.track(df$sectors, y = df$y, # 這里相當(dāng)于自動(dòng)分配y軸范圍
    panel.fun = function(x, y) { # 定義添加點(diǎn)和文字的細(xì)節(jié),你可以去掉這個(gè)函數(shù)試試看
        circos.text(CELL_META$xcenter, 
            CELL_META$cell.ylim[2] + mm_y(5), 
            CELL_META$sector.index)
        circos.axis(labels.cex = 0.6)
        }
    )


col = rep(c("#FF0000""#00FF00"), 4)

# 添加點(diǎn)
circos.trackPoints(df$sectors, df$x, df$y, col = col, pch = 16, cex = 0.5)
# 添加文字
circos.text(-10.5"text", sector.index = "a", track.index = 1)

# 添加第2個(gè)圓環(huán)
bgcol = rep(c("#EFEFEF""#CCCCCC"), 4)
circos.trackHist(df$sectors, df$x, bin.size = 0.2, bg.col = bgcol, col = NA)

# 添加第3個(gè)圓環(huán)
circos.track(df$sectors, x = df$x, y = df$y,
    panel.fun = function(x, y) {
        ind = sample(length(x), 10)
        x2 = x[ind]
        y2 = y[ind]
        od = order(x2)
        circos.lines(x2[od], y2[od])
})

如果我們要對(duì)某一個(gè)圓環(huán)的某個(gè)扇區(qū)(也就是某個(gè)panel)進(jìn)行修改,可以使用circos.update,但是要注意,這個(gè)函數(shù)不能修改位置相關(guān)的東西。

比如我們要修改d這個(gè)扇區(qū)的第2層圓環(huán),可以在運(yùn)行完以上代碼后運(yùn)行以下代碼:

circos.update(sector.index = "d"# 選擇扇區(qū)
              track.index = 2,    # 選擇圓環(huán)
              bg.col = "#FF8080", bg.border = "black"# 修改顏色
circos.points(x = -2:2, y = rep(0.55), col = "white")
circos.text(CELL_META$xcenter, CELL_META$ycenter, "updated", col = "white")

接下來還可以繼續(xù)添加圓環(huán):

circos.track(ylim = c(01), panel.fun = function(x, y) {
    xlim = CELL_META$xlim
    ylim = CELL_META$ylim
    breaks = seq(xlim[1], xlim[2], by = 0.1)
    n_breaks = length(breaks)
    circos.rect(breaks[-n_breaks], rep(ylim[1], n_breaks - 1),
                breaks[-1], rep(ylim[2], n_breaks - 1),
                col = rand_color(n_breaks), border = NA)
})

當(dāng)你把圓環(huán)都畫完之后,還可以使用線條或者條帶連接不同的扇區(qū):

circos.link("a"0"b"0, h = 0.4)
circos.link("c", c(-0.50.5), "d", c(-0.5,0.5), 
            col = "red",border = "blue", h = 0.2)
circos.link("e"0"g", c(-1,1), 
            col = "green", border = "black", lwd = 2, lty = 2)

當(dāng)你完成整個(gè)圓環(huán)圖的繪制后,一定要記得重置圖形參數(shù):

circos.clear()

添加圖形元素的方式

畫圓環(huán)圖首先要初始化,然后添加圓環(huán),再然后才是添加各種圖形元素,比如點(diǎn)、線、文本、坐標(biāo)軸等。

添加這些圖形元素的方式有3種:

  1. 使用circos.points()circos.lines()等低級(jí)繪圖函數(shù)進(jìn)行添加,但是這種方式需要自己寫for循環(huán),逐個(gè)panel進(jìn)行添加,需要自己根據(jù)類別劃分?jǐn)?shù)據(jù);
  2. 使用circos.trackPoints()、circos.trackLines()等函數(shù)添加,不需要自己寫循環(huán);
  3. 使用panel.fun添加,這種方式最為強(qiáng)大,但是需要一點(diǎn)理解,作者是比較推薦這種方式的,下面會(huì)詳細(xì)介紹。

panel.fun需要兩個(gè)參數(shù):xy,分別表示在當(dāng)前panel中的橫坐標(biāo)和縱坐標(biāo)。

以下是一個(gè)簡(jiǎn)單的示例。在扇區(qū)a中,x的值是1:3,在扇區(qū)b中,x的值是4:5:

sectors = c("a""a""a""b""b")
x = 1:5
y = 5:1


circos.initialize(sectors = sectors, x=x)
circos.track(sectors, x = x, y = y,
    panel.fun = function(x, y) {
      circos.points(x, y)
      circos.text(CELL_META$xcenter, # 橫坐標(biāo)
            CELL_META$cell.ylim[2] + mm_y(5),  #縱坐標(biāo)
            CELL_META$sector.index)
})
circos.clear()

CELL_META$xxxx其實(shí)是get.cell.meta.data()的縮寫,可以幫你提取當(dāng)前panel的信息,比如CELL_META$xcenter會(huì)提取當(dāng)前panel的橫坐標(biāo)的中心點(diǎn),CELL_META$cell.ylim是提取當(dāng)前panel的縱坐標(biāo),CELL_META$sector.index提取當(dāng)前panel的標(biāo)簽。

我們也可以直接使用get.cell.meta.data()函數(shù),但是不如用CELL_META$簡(jiǎn)潔。以下第二個(gè)圓環(huán)就是用的get.cell.meta.data()函數(shù):

sectors = c("a""a""a""b""b")
x = 1:5
y = 5:1

# 初始化
circos.initialize(sectors = sectors, x=x)

# 添加第一個(gè)圓環(huán),標(biāo)簽在圓環(huán)外面
circos.track(sectors, x = x, y = y,
    panel.fun = function(x, y) {
      circos.points(x, y)
      circos.text(CELL_META$xcenter, # 橫坐標(biāo)
            CELL_META$cell.ylim[2] + mm_y(5),  #縱坐標(biāo)
            CELL_META$sector.index)
})
# 添加第二個(gè)圓環(huán),把標(biāo)簽放在圓環(huán)里面
circos.track(sectors, y = y, panel.fun = function(x, y) {
    sector.index = get.cell.meta.data("sector.index")
    xcenter = get.cell.meta.data("xcenter")
    ycenter = get.cell.meta.data("ycenter")
    circos.text(xcenter, ycenter, sector.index)
})
circos.clear()

圓形熱圖

圓形熱圖非常常見,以前是通過circos.rect實(shí)現(xiàn),但是0.4.10版本以后提供了一個(gè)circos.heatmap函數(shù),可以直接繪制圓形熱圖,非常方便。

數(shù)據(jù)準(zhǔn)備時(shí)也要提供一個(gè)數(shù)值型矩陣(用來畫熱圖),除此之外,還需要一個(gè)分組變量,用來分割熱圖。

rm(list = ls())
set.seed(123)
mat1 = rbind(cbind(matrix(rnorm(50*5, mean = 1), nr = 50),
                   matrix(rnorm(50*5, mean = -1), nr = 50)),
             cbind(matrix(rnorm(50*5, mean = -1), nr = 50),
                   matrix(rnorm(50*5, mean = 1), nr = 50))
            )
rownames(mat1) = paste0("R"1:100)
colnames(mat1) = paste0("C"1:10)
mat1 = mat1[sample(100100), ] # 畫熱圖的矩陣
mat1[1:4,1:4]
            C1         C2         C3         C4
R97 -2.1986224 -1.1271486 -1.8308115 -1.1624219
R49 1.7799651 0.7642996 3.1001089 0.3888341
R50 0.9166309 -0.0264209 -0.2870305 -0.1854801
R42 0.7920827 1.5483970 0.7378025 0.6753141
# 分組變量
split = sample(letters[1:5], 100, replace = TRUE)
spilt = factor(split, levels = letters[1:5])
col_fun1 = colorRamp2(c(-202), c("blue""white""red"))

這個(gè)數(shù)據(jù)如果直接畫熱圖是這樣的:

library(ComplexHeatmap)
Heatmap(mat1, row_split = split)

如果要畫圓形熱圖,是這樣的:

circos.heatmap(mat1, split = split, col = col_fun1,
               track.height = 0.4# 圓環(huán)的寬度
               show.sector.labels = T#顯示圓環(huán)的標(biāo)簽
               rownames.side = "outside"# 行名顯示在外側(cè)
               dend.side = "inside" # 聚類樹顯示在內(nèi)側(cè)
               )
circos.clear()

各種文本都可以進(jìn)行各種自定義設(shè)置,比如顏色、大小、字體等。

聚類樹也可以進(jìn)行修改,比如重新排序或者使用不同的顏色等。需要借助dend.callback參數(shù)以及自定義函數(shù)實(shí)現(xiàn)。自定義函數(shù)需要3個(gè)參數(shù):

  • dend:當(dāng)前扇區(qū)的聚類樹
  • m:屬于當(dāng)前扇區(qū)的熱圖
  • si:當(dāng)前扇區(qū)的編號(hào)(或者名字)

比如重新設(shè)置聚類樹的順序:

library(dendsort)
circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "inside",
    dend.callback = function(dend, m, si) {
        dendsort(dend)
    }
)
circos.clear()

或者給聚類樹添加不同的顏色:

library(dendextend)
dend_col = structure(1:5, names = letters[1:5])
circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "inside",
               dend.track.height = 0.2,
               dend.callback = function(dend, m, si) {
        # when k = 1, it renders one same color for the whole dendrogram
                 color_branches(dend, k = 1, col = dend_col[si])
                 }
        )
circos.clear()

增加多個(gè)圓環(huán)也是一模一樣的方法。

# 第2個(gè)熱圖的數(shù)據(jù)
mat2 = mat1[sample(100100), ] # randomly permute mat1 by rows

# 第2個(gè)熱圖的顏色
col_fun2 = colorRamp2(c(-202), c("green""white""red"))

# 繪制兩個(gè)圓形熱圖
circos.heatmap(mat1, split = split, col = col_fun1, dend.side = "outside")
circos.heatmap(mat2, col = col_fun2)
circos.clear()

更加復(fù)雜的例子,大家可以至官網(wǎng)學(xué)習(xí):https://jokergoo./circlize_book/book/

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多