【r<-包】ComplexHeatmap(2):創(chuàng)建一個(gè)簡(jiǎn)單的熱圖

Author: Zuguang Gu ( z.gu@dkfz.de )
翻譯:詩(shī)翔
Date: 2018-10-30


一個(gè)簡(jiǎn)單的熱圖通常用戶快速瀏覽數(shù)據(jù)武翎。一個(gè)熱圖列表的特殊例子就是只包含一個(gè)熱圖鹃操。相比于已經(jīng)存在的工具歹撒, ComplexHeatmap包提供了一種更靈活的方式支持單個(gè)熱圖的可視化催植。在下面的例子中许饿,我們會(huì)說(shuō)明如何設(shè)置參數(shù)以顯示一個(gè)簡(jiǎn)單的熱圖味混。

首先讓我們載入包并生成一個(gè)隨機(jī)矩陣眼姐。

library(ComplexHeatmap)
library(circlize)

set.seed(123)

mat = cbind(rbind(matrix(rnorm(16, -1), 4), matrix(rnorm(32, 1), 8)),
            rbind(matrix(rnorm(24, 1), 4), matrix(rnorm(48, -1), 8)))

# 置換行列
mat = mat[sample(nrow(mat), nrow(mat)), sample(ncol(mat), ncol(mat))]

rownames(mat) = paste0("R", 1:12)
colnames(mat) = paste0("C", 1:10)

使用默認(rèn)的設(shè)置繪制熱圖。熱圖默認(rèn)的樣式跟其他相似熱圖函數(shù)生成的效果很接近窃祝。

Heatmap(mat)

顏色

大多數(shù)情況下掐松,熱圖可視化含連續(xù)值得矩陣。在這種情況下粪小,用戶需要提供一個(gè)顏色映射函數(shù)大磺。一個(gè)顏色映射函數(shù)需要接收一個(gè)數(shù)值向量并返回對(duì)應(yīng)的顏色。circlize包提供的colorRamp2()對(duì)于生成這樣的函數(shù)很有用探膊。當(dāng)前該函數(shù)通過(guò)LAB顏色空間線性地在每個(gè)區(qū)間插入顏色杠愧。

在下面的例子中,-3到3的區(qū)間被線性插入值用于獲取對(duì)應(yīng)的顏色逞壁,值大于3的被映射為紅色流济,小于-3的被映射為綠色(因此這里的顏色對(duì)于異常值具有魯棒性)。

mat2 = mat
mat2[1, 1] = 100000
Heatmap(mat2, col = colorRamp2(c(-3, 0, 3), c("green", "white", "red")), 
    cluster_rows = FALSE, cluster_columns = FALSE)

如果矩陣值是連續(xù)的猾担,你也可以提供一個(gè)顏色向量袭灯,顏色會(huì)根據(jù)第"k"個(gè)百分位進(jìn)行插值。但是記住這種方法對(duì)于異常點(diǎn)沒(méi)有魯棒性绑嘹。

Heatmap(mat, col = rev(rainbow(10)))

如果矩陣包含離散值(要么是數(shù)值的要么是字符串)稽荧,顏色應(yīng)該指定為一個(gè)命名向量用于將離散值映射為顏色。如果顏色沒(méi)有名字工腋,那么顏色的順序會(huì)對(duì)應(yīng)于unique(mat)的順序姨丈。

discrete_mat = matrix(sample(1:4, 100, replace = TRUE), 10, 10)
colors = structure(circlize::rand_color(4), names = c("1", "2", "3", "4"))
Heatmap(discrete_mat, col = colors)

或者一個(gè)字符串矩陣:

discrete_mat = matrix(sample(letters[1:4], 100, replace = TRUE), 10, 10)
colors = structure(circlize::rand_color(4), names = letters[1:4])
Heatmap(discrete_mat, col = colors)

你可以看到,對(duì)于數(shù)值型矩陣(無(wú)論它是連續(xù)映射還是離散映射)擅腰,默認(rèn)兩個(gè)維度都會(huì)進(jìn)行聚類蟋恬。而對(duì)于字符串矩陣,聚類默認(rèn)是被抑制的趁冈。

熱圖中允許存在NA值歼争。你可以通過(guò)na_col參數(shù)控制NA值的顏色拜马。包含NA值矩陣也可以使用Heatmap()函數(shù)聚類(因?yàn)?code>dist()函數(shù)接收NA值),使用“pearson”沐绒、 “spearman” 或 “kendall” 方法會(huì)給出警告信息俩莽。

mat_with_na = mat
mat_with_na[sample(c(TRUE, FALSE), nrow(mat)*ncol(mat), replace = TRUE, prob = c(1, 9))] = NA
Heatmap(mat_with_na, na_col = "orange", clustering_distance_rows = "pearson")
## Warning in get_dist(submat, distance): NA exists in the matrix, calculating distance by removing NA
## values.

對(duì)顏色插值來(lái)說(shuō)顏色空間非常重要。默認(rèn)情況下乔遮,顏色都是在LAB color space中線性插值扮超,但你可以使用,colorRamp2()函數(shù)選擇其他的顏色空間。比較下面的兩幅圖:

f1 = colorRamp2(seq(min(mat), max(mat), length = 3), c("blue", "#EEEEEE", "red"))
f2 = colorRamp2(seq(min(mat), max(mat), length = 3), c("blue", "#EEEEEE", "red"), space = "RGB")
Heatmap(mat, col = f1, column_title = "LAB color space") +
Heatmap(mat, col = f2, column_title = "RGB color space")

下面圖形顯示了不同顏色空間的差別(使用HilbertCurve包繪制)蹋肮。

標(biāo)題

熱圖的名字默認(rèn)用作熱圖圖例的標(biāo)題出刷。如果你將多個(gè)熱圖放到一起,名字可以作為唯一的標(biāo)識(shí)符坯辩。

Heatmap(mat, name = "foo")

熱圖圖例的標(biāo)題可以通過(guò)參數(shù)heatmap_legend_param進(jìn)行更改馁龟。

Heatmap(mat, heatmap_legend_param = list(title = "legend"))

你可以設(shè)定熱圖的行與列標(biāo)題,行與列圖形參數(shù)分別通過(guò)row_title_gpcolumn_title_gp選項(xiàng)指定濒翻,使用gpar()函數(shù)進(jìn)行具體的設(shè)置屁柏。

Heatmap(mat, name = "foo", column_title = "I am a column title", 
    row_title = "I am a row title")
Heatmap(mat, name = "foo", column_title = "I am a big column title", 
    column_title_gp = gpar(fontsize = 20, fontface = "bold"))

標(biāo)題的選擇可以使用row_title_rotcolumn_title_rot設(shè)置啦膜,但只支持水平和垂直旋轉(zhuǎn)有送。

Heatmap(mat, name = "foo", row_title = "row title", row_title_rot = 0)

聚類

聚類是熱圖可視化的關(guān)鍵特征之一。該包支持高度靈活的聚類設(shè)定僧家。

首先有一些聚類的通用設(shè)定雀摘,例如是否顯示樹(shù)狀圖、其大小八拱。

Heatmap(mat, name = "foo", cluster_rows = FALSE)
Heatmap(mat, name = "foo", show_column_dend = FALSE)
Heatmap(mat, name = "foo", row_dend_side = "right")
Heatmap(mat, name = "foo", column_dend_height = unit(2, "cm"))

有3種方式指定聚類的距離度量:

  • 使用提前設(shè)定的選項(xiàng)阵赠,合法的值包括dist()函數(shù)支持的方法以及pearsonspearmankendall肌稻。
  • 一個(gè)從矩陣中計(jì)算距離的自定義函數(shù)清蚀,函數(shù)僅包含一個(gè)參數(shù)
  • 一個(gè)從兩個(gè)向量中計(jì)算距離的自定義函數(shù),函數(shù)僅包含2個(gè)參數(shù)
Heatmap(mat, name = "foo", clustering_distance_rows = "pearson")
Heatmap(mat, name = "foo", clustering_distance_rows = function(m) dist(m))
Heatmap(mat, name = "foo", clustering_distance_rows = function(x, y) 1 - cor(x, y))

基于這個(gè)特征爹谭,我們開(kāi)源使用配對(duì)距離應(yīng)用聚類使得可以魯棒地處理異常值枷邪。

mat_with_outliers = mat
for(i in  1:10) mat_with_outliers[i, i] = 1000
robust_dist = function(x, y) {
    qx = quantile(x, c(0.1, 0.9))
    qy = quantile(y, c(0.1, 0.9))
    l = x > qx[1] & x < qx[2] & y > qy[1] & y < qy[2]
    x = x[l]
    y = y[l]
    sqrt(sum((x - y)^2))
}
Heatmap(mat_with_outliers, name = "foo", 
    col = colorRamp2(c(-3, 0, 3), c("green", "white", "red")),
    clustering_distance_rows = robust_dist,
    clustering_distance_columns = robust_dist)

如果提供了距離方法,你也可以對(duì)字符串矩陣進(jìn)行聚類诺凡。cell_fun參數(shù)會(huì)在后面進(jìn)行解釋东揣。

mat_letters = matrix(sample(letters[1:4], 100, replace = TRUE), 10)
# distance in th ASCII table
dist_letters = function(x, y) {
    x = strtoi(charToRaw(paste(x, collapse = "")), base = 16)
    y = strtoi(charToRaw(paste(y, collapse = "")), base = 16)
    sqrt(sum((x - y)^2))
}
Heatmap(mat_letters, name = "foo", col = structure(2:5, names = letters[1:4]),
    clustering_distance_rows = dist_letters, clustering_distance_columns = dist_letters,
    cell_fun = function(j, i, x, y, w, h, col) {
        grid.text(mat_letters[i, j], x, y)
    })

創(chuàng)建層次聚類的方法可以通過(guò)選項(xiàng)clustering_method_rowsclustering_method_columns指定,可以使用hclust()函數(shù)支持的方法腹泌。

Heatmap(mat, name = "foo", clustering_method_rows = "single")

默認(rèn)嘶卧,聚類由hclust()實(shí)施。但你可以通過(guò)cluster_rowscluster_columns指定由其他方法生成的hclustdendrogram對(duì)象凉袱。在下面的例子中芥吟,我們使用來(lái)自cluster包的diana()agnes()函數(shù)進(jìn)行聚類侦铜。

library(cluster)
Heatmap(mat, name = "foo", cluster_rows = as.dendrogram(diana(mat)),
   cluster_columns = as.dendrogram(agnes(t(mat))))

在原始的Heatmap()函數(shù)中,行或列的樹(shù)狀圖都是根據(jù)使得特征可以最大地進(jìn)行分隔而排序的钟鸵,Heatmap()提供了選項(xiàng)進(jìn)行調(diào)整泵额。除了默認(rèn)的重排序方法,你也可以先生成一個(gè)樹(shù)狀圖携添,然后應(yīng)用一些重排序的方法嫁盲,然后將重排序的樹(shù)狀圖傳給cluster_rows參數(shù)。

比較下面3幅圖:

pushViewport(viewport(layout = grid.layout(nr = 1, nc = 3)))
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 1))
draw(Heatmap(mat, name = "foo", row_dend_reorder = FALSE, column_title = "no reordering"), newpage = FALSE)
upViewport()

pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2))
draw(Heatmap(mat, name = "foo", row_dend_reorder = TRUE, column_title = "applied reordering"), newpage = FALSE)
upViewport()

library(dendsort)
dend = dendsort(hclust(dist(mat)))
pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 3))
draw(Heatmap(mat, name = "foo", cluster_rows = dend, row_dend_reorder = FALSE, 
    column_title = "reordering by dendsort"), newpage = FALSE)
upViewport(2)

你可以使用dendextend包渲染你的dendrogram對(duì)象烈掠,自定義樹(shù)狀圖羞秤。

library(dendextend)
dend = hclust(dist(mat))
dend = color_branches(dend, k = 2)
Heatmap(mat, name = "foo", cluster_rows = dend)

更通用地,cluster_rowscluster_columns可以提供計(jì)算聚類的函數(shù)左敌。自定義函數(shù)的輸入需要是一個(gè)矩陣瘾蛋,返回值需要時(shí)一個(gè)hclust或者dendrogram對(duì)象。

Heatmap(mat, name = "foo", cluster_rows = function(m) as.dendrogram(diana(m)),
    cluster_columns = function(m) as.dendrogram(agnes(m)))

fastcluster::hclust實(shí)現(xiàn)了更快版本的hclust矫限。

# code not run when building the vignette
Heatmap(mat, name = "foo", cluster_rows = function(m) fastcluster::hclust(dist(m)),
    cluster_columns = function(m) fastcluster::hclust(dist(m))) # for column cluster, m will be automatically transposed

為了更方便的使用快速版本的hclust哺哼,我們可以設(shè)定一個(gè)全局選項(xiàng)。

# code not run when building the vignette
ht_global_opt(fast_hclust = TRUE)
# now hclust from fastcluster package is used in all heatmaps
Heatmap(mat, name = "foo")

聚類可以幫助調(diào)整行和列的順序叼风。但是你仍然需要手動(dòng)設(shè)定row_ordercolumn_order來(lái)設(shè)定順序取董。注意這個(gè)時(shí)候你需要將聚類給關(guān)掉,另外如果矩陣有行名和列名也可以直接通過(guò)名字調(diào)整順序无宿。

Heatmap(mat, name = "foo", cluster_rows = FALSE, cluster_columns = FALSE, 
    row_order = 12:1, column_order = 10:1)

注意row_dend_reorderrow_order是不同的茵汰。前者應(yīng)用于樹(shù)狀圖。因?yàn)閷?duì)于樹(shù)狀圖的任何結(jié)點(diǎn)孽鸡,旋轉(zhuǎn)兩個(gè)葉子都會(huì)給出唯一的樹(shù)狀圖蹂午。當(dāng)row_order設(shè)置時(shí),樹(shù)狀圖會(huì)被抑制彬碱。

維度名字

維度名字的側(cè)邊豆胸、可視度和圖形參數(shù)可以進(jìn)行如下設(shè)置。

Heatmap(mat, name = "foo", row_names_side = "left", row_dend_side = "right", 
    column_names_side = "top", column_dend_side = "bottom")
Heatmap(mat, name = "foo", show_row_names = FALSE)
Heatmap(mat, name = "foo", row_names_gp = gpar(fontsize = 20))
Heatmap(mat, name = "foo", row_names_gp = gpar(col = c(rep("red", 4), rep("blue", 8))))

當(dāng)前行名和列名不支持旋轉(zhuǎn)巷疼。文字旋轉(zhuǎn)可以通過(guò)熱圖注釋實(shí)現(xiàn)(這在熱圖注釋手冊(cè)中將會(huì)看到)晚胡。

按行切分熱圖

熱圖可以按行切分。這可以增加熱圖中的分組可視化皮迟。參數(shù)km設(shè)置大于1的值意味著對(duì)行實(shí)施K-means聚類并在每個(gè)子類中實(shí)施聚類搬泥。

Heatmap(mat, name = "foo", km = 2)

更通用地,split可以傳入一個(gè)分割熱圖行不同組合水平的向量或是數(shù)據(jù)框伏尼。實(shí)際上k-means聚類也是先聚類得到行的分類然后使用split實(shí)現(xiàn)切分忿檩。每一個(gè)行切片的標(biāo)題可以通過(guò)combined_name_fun參數(shù)設(shè)定。每個(gè)切片的順序通過(guò)split中每個(gè)變量的水平控制爆阶。

Heatmap(mat, name = "foo", split = rep(c("A", "B"), 6))
Heatmap(mat, name = "foo", split = data.frame(rep(c("A", "B"), 6), rep(c("C", "D"), each = 6)))
Heatmap(mat, name = "foo", split = data.frame(rep(c("A", "B"), 6), rep(c("C", "D"), each = 6)), 
    combined_name_fun = function(x) paste(x, collapse = "\n"))
Heatmap(mat, name = "foo", km = 2, split = factor(rep(c("A", "B"), 6), levels = c("B", "A")), 
    combined_name_fun = function(x) paste(x, collapse = "\n"))
Heatmap(mat, name = "foo", km = 2, split = rep(c("A", "B"), 6), combined_name_fun = NULL)

如果你不喜歡默認(rèn)的k-means分類方法燥透,你可以通過(guò)將分類向量傳入split的方式使用其他方法沙咏。

pa = pam(mat, k = 3)
Heatmap(mat, name = "foo", split = paste0("pam", pa$clustering))

如果row_order設(shè)置了,在每個(gè)切片里面班套,行依然是按順序排列的肢藐。

Heatmap(mat, name = "foo", row_order = 12:1, cluster_rows = FALSE, km = 2)

gap的高度可以通過(guò)gap參數(shù)控制(單個(gè)unit或者units向量)。

Heatmap(mat, name = "foo", split = paste0("pam", pa$clustering), gap = unit(5, "mm"))

字符串矩陣也可以通過(guò)split參數(shù)切分吱韭。

Heatmap(discrete_mat, name = "foo", col = 1:4,
    split = rep(letters[1:2], each = 5))

當(dāng)按行切分的時(shí)候吆豹,也可以通過(guò)圖形參數(shù)自定義行標(biāo)題和行名。

Heatmap(mat, name = "foo", km = 2, row_title_gp = gpar(col = c("red", "blue"), font = 1:2),
    row_names_gp = gpar(col = c("green", "orange"), fontsize = c(10, 14)))

用戶可能已經(jīng)有一個(gè)行的樹(shù)狀圖了理盆,他們可能想要將樹(shù)狀圖分為k個(gè)子樹(shù)痘煤。這種情況下,split可以指定一個(gè)數(shù)猿规。

dend = hclust(dist(mat))
dend = color_branches(dend, k = 2)
Heatmap(mat, name = "foo", cluster_rows = dend, split = 2)

或者可以直接指定split一個(gè)整數(shù)衷快。注意這跟km不同。如果km設(shè)置了姨俩,首先是要k-means聚類蘸拔,然后對(duì)每個(gè)子類進(jìn)行聚類。當(dāng)split是一個(gè)整數(shù)的時(shí)候环葵,直接對(duì)整個(gè)矩陣進(jìn)行聚類调窍,然后根據(jù)cutree()切分。

Heatmap(mat, name = "foo", split = 2)

自定義熱圖主體

rect_gp參數(shù)提供了熱圖主體的基本圖形設(shè)置(注意fill參數(shù)已經(jīng)被禁用了)积担。

Heatmap(mat, name = "foo", rect_gp = gpar(col = "green", lty = 2, lwd = 2))

熱圖主體可以自定義陨晶。默認(rèn)熱圖主體由帶不同填充色的矩形數(shù)組組成(這里稱為cell)。如果rect_gp中的type設(shè)置為none帝璧,整個(gè)cell數(shù)組被初始化但沒(méi)有圖形,然后用戶可以通過(guò)cell_fun自定義他們自己的圖形函數(shù)湿刽。cell_fun應(yīng)用于熱圖的每一個(gè)cell的烁,它需要為每一個(gè)cell提供下面的信息:

  • j - 矩陣中的列索引。
  • i - 矩陣中的行索引
  • x - cell中心點(diǎn)的x坐標(biāo)
  • y - cell中心點(diǎn)的y坐標(biāo)
  • width - cell的寬度
  • height - cell 的高度
  • fill - cell的填充色

最常見(jiàn)的使用是給熱圖添加數(shù)值信息诈闺。

Heatmap(mat, name = "foo", cell_fun = function(j, i, x, y, width, height, fill) {
    grid.text(sprintf("%.1f", mat[i, j]), x, y, gp = gpar(fontsize = 10))
})

下面的例子中渴庆,我們創(chuàng)建一個(gè)類似corrplot包提供的相關(guān)矩陣圖。

cor_mat = cor(mat)
od = hclust(dist(cor_mat))$order
cor_mat = cor_mat[od, od]
nm = rownames(cor_mat)
col_fun = circlize::colorRamp2(c(-1, 0, 1), c("green", "white", "red"))
# `col = col_fun` here is used to generate the legend
Heatmap(cor_mat, name = "correlation", col = col_fun, rect_gp = gpar(type = "none"), 
    cell_fun = function(j, i, x, y, width, height, fill) {
        grid.rect(x = x, y = y, width = width, height = height, gp = gpar(col = "grey", fill = NA))
        if(i == j) {
            grid.text(nm[i], x = x, y = y)
        } else if(i > j) {
            grid.circle(x = x, y = y, r = abs(cor_mat[i, j])/2 * min(unit.c(width, height)), 
                gp = gpar(fill = col_fun(cor_mat[i, j]), col = NA))
        } else {
            grid.text(sprintf("%.1f", cor_mat[i, j]), x, y, gp = gpar(fontsize = 8))
        }
    }, cluster_rows = FALSE, cluster_columns = FALSE,
    show_row_names = FALSE, show_column_names = FALSE)

最后一個(gè)例子是可視化圍棋雅镊,輸入數(shù)據(jù)記錄在游戲中的形勢(shì)襟雷。

str = "B[cp];W[pq];B[dc];W[qd];B[eq];W[od];B[de];W[jc];B[qk];W[qn]
;B[qh];W[ck];B[ci];W[cn];B[hc];W[je];B[jq];W[df];B[ee];W[cf]
;B[ei];W[bc];B[ce];W[be];B[bd];W[cd];B[bf];W[ad];B[bg];W[cc]
;B[eb];W[db];B[ec];W[lq];B[nq];W[jp];B[iq];W[kq];B[pp];W[op]
;B[po];W[oq];B[rp];W[ql];B[oo];W[no];B[pl];W[pm];B[np];W[qq]
;B[om];W[ol];B[pk];W[qp];B[on];W[rm];B[mo];W[nr];B[rl];W[rk]
;B[qm];W[dp];B[dq];W[ql];B[or];W[mp];B[nn];W[mq];B[qm];W[bp]
;B[co];W[ql];B[no];W[pr];B[qm];W[dd];B[pn];W[ed];B[bo];W[eg]
;B[ef];W[dg];B[ge];W[gh];B[gf];W[gg];B[ek];W[ig];B[fd];W[en]
;B[bn];W[ip];B[dm];W[ff];B[cb];W[fe];B[hp];W[ho];B[hq];W[el]
;B[dl];W[fk];B[ej];W[fp];B[go];W[hn];B[fo];W[em];B[dn];W[eo]
;B[gp];W[ib];B[gc];W[pg];B[qg];W[ng];B[qc];W[re];B[pf];W[of]
;B[rc];W[ob];B[ph];W[qo];B[rn];W[mi];B[og];W[oe];B[qe];W[rd]
;B[rf];W[pd];B[gm];W[gl];B[fm];W[fl];B[lj];W[mj];B[lk];W[ro]
;B[hl];W[hk];B[ik];W[dk];B[bi];W[di];B[dj];W[dh];B[hj];W[gj]
;B[li];W[lh];B[kh];W[lg];B[jn];W[do];B[cl];W[ij];B[gk];W[bl]
;B[cm];W[hk];B[jk];W[lo];B[hi];W[hm];B[gk];W[bm];B[cn];W[hk]
;B[il];W[cq];B[bq];W[ii];B[sm];W[jo];B[kn];W[fq];B[ep];W[cj]
;B[bk];W[er];B[cr];W[gr];B[gk];W[fj];B[ko];W[kp];B[hr];W[jr]
;B[nh];W[mh];B[mk];W[bb];B[da];W[jh];B[ic];W[id];B[hb];W[jb]
;B[oj];W[fn];B[fs];W[fr];B[gs];W[es];B[hs];W[gn];B[kr];W[is]
;B[dr];W[fi];B[bj];W[hd];B[gd];W[ln];B[lm];W[oi];B[oh];W[ni]
;B[pi];W[ki];B[kj];W[ji];B[so];W[rq];B[if];W[jf];B[hh];W[hf]
;B[he];W[ie];B[hg];W[ba];B[ca];W[sp];B[im];W[sn];B[rm];W[pe]
;B[qf];W[if];B[hk];W[nj];B[nk];W[lr];B[mn];W[af];B[ag];W[ch]
;B[bh];W[lp];B[ia];W[ja];B[ha];W[sf];B[sg];W[se];B[eh];W[fh]
;B[in];W[ih];B[ae];W[so];B[af]"

然后我們將它轉(zhuǎn)換為一個(gè)矩陣:

str = gsub("\\n", "", str)
step = strsplit(str, ";")[[1]]
type = gsub("(B|W).*", "\\1", step)
row = gsub("(B|W)\\[(.).\\]", "\\2", step)
column = gsub("(B|W)\\[.(.)\\]", "\\2", step)

mat = matrix(nrow = 19, ncol = 19)
rownames(mat) = letters[1:19]
colnames(mat) = letters[1:19]
for(i in seq_along(row)) {
    mat[row[i], column[i]] = type[i]
}
mat
##   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o   p   q   r   s  
## a NA  NA  NA  "W" "B" "B" "B" NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA  NA 
## b "W" "W" "W" "B" "W" "B" "B" "B" "B" "B" "B" "W" "W" "B" "B" "W" "B" NA  NA 
## c "B" "B" "W" "W" "B" "W" NA  "W" "B" "W" "W" "B" "B" "B" "B" "B" "W" "B" NA 
## d "B" "W" "B" "W" "B" "W" "W" "W" "W" "B" "W" "B" "B" "B" "W" "W" "B" "B" NA 
## e NA  "B" "B" "W" "B" "B" "W" "B" "B" "B" "B" "W" "W" "W" "W" "B" "B" "W" "W"
## f NA  NA  NA  "B" "W" "W" NA  "W" "W" "W" "W" "W" "B" "W" "B" "W" "W" "W" "B"
## g NA  NA  "B" "B" "B" "B" "W" "W" NA  "W" "B" "W" "B" "W" "B" "B" NA  "W" "B"
## h "B" "B" "B" "W" "B" "W" "B" "B" "B" "B" "B" "B" "W" "W" "W" "B" "B" "B" "B"
## i "B" "W" "B" "W" "W" "W" "W" "W" "W" "W" "B" "B" "B" "B" NA  "W" "B" NA  "W"
## j "W" "W" "W" NA  "W" "W" NA  "W" "W" NA  "B" NA  NA  "B" "W" "W" "B" "W" NA 
## k NA  NA  NA  NA  NA  NA  NA  "B" "W" "B" NA  NA  NA  "B" "B" "W" "W" "B" NA 
## l NA  NA  NA  NA  NA  NA  "W" "W" "B" "B" "B" NA  "B" "W" "W" "W" "W" "W" NA 
## m NA  NA  NA  NA  NA  NA  NA  "W" "W" "W" "B" NA  NA  "B" "B" "W" "W" NA  NA 
## n NA  NA  NA  NA  NA  NA  "W" "B" "W" "W" "B" NA  NA  "B" "B" "B" "B" "W" NA 
## o NA  "W" NA  "W" "W" "W" "B" "B" "W" "B" NA  "W" "B" "B" "B" "W" "W" "B" NA 
## p NA  NA  NA  "W" "W" "B" "W" "B" "B" NA  "B" "B" "W" "B" "B" "B" "W" "W" NA 
## q NA  NA  "B" "W" "B" "B" "B" "B" NA  NA  "B" "W" "B" "W" "W" "W" "W" NA  NA 
## r NA  NA  "B" "W" "W" "B" NA  NA  NA  NA  "W" "B" "B" "B" "W" "B" "W" NA  NA 
## s NA  NA  NA  NA  "W" "W" "B" NA  NA  NA  NA  NA  "B" "W" "W" "W" NA  NA  NA

基于矩陣的值我們放上黑子和白子。

Heatmap(mat, name = "go", rect_gp = gpar(type = "none"),
    cell_fun = function(j, i, x, y, w, h, col) {
        grid.rect(x, y, w, h, gp = gpar(fill = "#dcb35c", col = NA))
        if(i == 1) {
            grid.segments(x, y-h*0.5, x, y)
        } else if(i == nrow(mat)) {
            grid.segments(x, y, x, y+h*0.5)
        } else {
            grid.segments(x, y-h*0.5, x, y+h*0.5)
        }
        if(j == 1) {
            grid.segments(x, y, x+w*0.5, y)        
        } else if(j == ncol(mat)) {
            grid.segments(x-w*0.5, y, x, y)
        } else {
            grid.segments(x-w*0.5, y, x+w*0.5, y)
        }

        if(i %in% c(4, 10, 16) & j %in% c(4, 10, 16)) {
            grid.points(x, y, pch = 16, size = unit(2, "mm"))
        }

        r = min(unit.c(w, h))*0.45
        if(is.na(mat[i, j])) {
        } else if(mat[i, j] == "W") {
            grid.circle(x, y, r, gp = gpar(fill = "white", col = "white"))
        } else if(mat[i, j] == "B") {
            grid.circle(x, y, r, gp = gpar(fill = "black", col = "black"))
        }
    },
    col = c("B" = "black", "W" = "white"),
    show_row_names = FALSE, show_column_names = FALSE,
    column_title = "One famous GO game",
    heatmap_legend_param = list(title = "Player", at = c("B", "W"), 
        labels = c("player1", "player2"), grid_border = "black")
)

將熱圖主體設(shè)置為光柵圖像

將圖形以PDF格式保存時(shí)保存質(zhì)量的最好方式仁烹。然而耸弄,如果行數(shù)太多(> 10000),輸出的PDF文件將非常之大卓缰。將熱圖渲染為光柵圖像可以減少文件大小计呈。Heatmap()函數(shù)中有4個(gè)選項(xiàng)控制如何生成光柵圖像:use_raster砰诵、raster_deviceraster_qualityraster_device_param捌显。

你可以通過(guò)raster_device選擇圖像設(shè)備(png茁彭、jpegtiff),使用raster_quality控制圖像質(zhì)量扶歪,raster_device_param可以傳入更多參數(shù)理肺。

會(huì)話信息

sessionInfo()
## R version 3.5.1 Patched (2018-07-12 r74967)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.5 LTS
## 
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.8-bioc/R/lib/libRblas.so
## LAPACK: /home/biocbuild/bbs-3.8-bioc/R/lib/libRlapack.so
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=en_US.UTF-8       
##  [4] LC_COLLATE=C               LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                  LC_ADDRESS=C              
## [10] LC_TELEPHONE=C             LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## attached base packages:
##  [1] stats4    parallel  grid      stats     graphics  grDevices utils     datasets  methods  
## [10] base     
## 
## other attached packages:
##  [1] dendextend_1.9.0      dendsort_0.3.3        cluster_2.0.7-1       IRanges_2.16.0       
##  [5] S4Vectors_0.20.0      BiocGenerics_0.28.0   HilbertCurve_1.12.0   circlize_0.4.4       
##  [9] ComplexHeatmap_1.20.0 knitr_1.20            markdown_0.8         
## 
## loaded via a namespace (and not attached):
##  [1] mclust_5.4.1           Rcpp_0.12.19           mvtnorm_1.0-8          lattice_0.20-35       
##  [5] png_0.1-7              class_7.3-14           assertthat_0.2.0       mime_0.6              
##  [9] R6_2.3.0               GenomeInfoDb_1.18.0    plyr_1.8.4             evaluate_0.12         
## [13] ggplot2_3.1.0          highr_0.7              pillar_1.3.0           GlobalOptions_0.1.0   
## [17] zlibbioc_1.28.0        rlang_0.3.0.1          lazyeval_0.2.1         diptest_0.75-7        
## [21] kernlab_0.9-27         whisker_0.3-2          GetoptLong_0.1.7       stringr_1.3.1         
## [25] RCurl_1.95-4.11        munsell_0.5.0          compiler_3.5.1         pkgconfig_2.0.2       
## [29] shape_1.4.4            nnet_7.3-12            tidyselect_0.2.5       gridExtra_2.3         
## [33] tibble_1.4.2           GenomeInfoDbData_1.2.0 viridisLite_0.3.0      crayon_1.3.4          
## [37] dplyr_0.7.7            MASS_7.3-51            bitops_1.0-6           gtable_0.2.0          
## [41] magrittr_1.5           scales_1.0.0           stringi_1.2.4          XVector_0.22.0        
## [45] viridis_0.5.1          flexmix_2.3-14         bindrcpp_0.2.2         robustbase_0.93-3     
## [49] fastcluster_1.1.25     HilbertVis_1.40.0      rjson_0.2.20           RColorBrewer_1.1-2    
## [53] tools_3.5.1            fpc_2.1-11.1           glue_1.3.0             trimcluster_0.1-2.1   
## [57] DEoptimR_1.0-8         purrr_0.2.5            colorspace_1.3-2       GenomicRanges_1.34.0  
## [61] prabclus_2.2-6         bindr_0.1.1            modeltools_0.2-22
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市善镰,隨后出現(xiàn)的幾起案子哲嘲,更是在濱河造成了極大的恐慌,老刑警劉巖媳禁,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眠副,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡竣稽,警方通過(guò)查閱死者的電腦和手機(jī)囱怕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)毫别,“玉大人娃弓,你說(shuō)我怎么就攤上這事〉夯拢” “怎么了台丛?”我有些...
    開(kāi)封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)砾肺。 經(jīng)常有香客問(wèn)我挽霉,道長(zhǎng),這世上最難降的妖魔是什么变汪? 我笑而不...
    開(kāi)封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任侠坎,我火速辦了婚禮,結(jié)果婚禮上裙盾,老公的妹妹穿的比我還像新娘实胸。我一直安慰自己,他們只是感情好番官,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布庐完。 她就那樣靜靜地躺著,像睡著了一般徘熔。 火紅的嫁衣襯著肌膚如雪门躯。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天近顷,我揣著相機(jī)與錄音生音,去河邊找鬼宁否。 笑死,一個(gè)胖子當(dāng)著我的面吹牛缀遍,可吹牛的內(nèi)容都是我干的慕匠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼域醇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼台谊!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起譬挚,我...
    開(kāi)封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤锅铅,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后减宣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體盐须,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年漆腌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贼邓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闷尿,死狀恐怖塑径,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情填具,我是刑警寧澤统舀,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站劳景,受9級(jí)特大地震影響誉简,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜枢泰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一描融、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衡蚂,春花似錦、人聲如沸骏庸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)具被。三九已至玻募,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間一姿,已是汗流浹背七咧。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工跃惫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人艾栋。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓爆存,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蝗砾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子先较,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容