Making A Single Heatmap
單熱圖(A single heatmap):主要用于快速查看數(shù)據(jù)。這是heatmap list的一個特例,它只包含一個熱圖。與現(xiàn)有工具相比,ComplexHeatmap包提供了更靈活的方法來支持單個heatmap的可視化。在下面的示例中,我們將演示如何設(shè)置參數(shù)來可視化單個熱圖。
加載包,生成一個隨機矩陣--(用于測試):
library(ComplexHeatmap)
library(circlize)
set.seed(123) #鄭寶童簡書上,提供了一個關(guān)于set.seed()函數(shù)的解析
mat = cbind(rbind(matrix(rnorm(16, -1), 4), matrix(rnorm(32, 1), 8)),
rbind(matrix(rnorm(24, 1), 4), matrix(rnorm(48, -1), 8)))
# permute the rows and columns 排列行和列
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)

Colors顏色
colorRamp2()的兩個參數(shù)分別是截斷值和相對應(yīng)的顏色. 當(dāng)前colorRamp2() 通過LAB color space在每個間隔中線性插入顏色。
在大多數(shù)情況下,熱圖可視化的是具有連續(xù)值的矩陣。 在這種情況下,用戶應(yīng)提供顏色映射功能。 顏色映射函數(shù)是輸入值向量返回顏色向量的函數(shù)。 ** circlize **包中的colorRamp2()有助于生成這些函數(shù)。colorRamp2()有兩個參數(shù)是:包含截斷值和相應(yīng)顏色的向量。
下方例子中, -3到3之間的值通過線性分布以獲得相應(yīng)的顏色, > 3:red ;< -3:green (所以這里演示的顏色映射函數(shù)對異常值也是穩(wěn)定可用的).--colorRamp2設(shè)置顏色
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ù)的,您還可以提供顏色向量,顏色將根據(jù)'k'分位數(shù)進行插值。 但請記住,這種方法對異常值并不穩(wěn)健。
Heatmap(mat, col = rev(rainbow(10)))

如果矩陣包含離散值(數(shù)字或字符),則應(yīng)將顏色指定給命名向量,以使從離散值映射到顏色成為可能。如果沒為顏色指定命名向量, 顏色順序?qū)?yīng)于unique(mat)的順序一致.(如下圖第二行,四種顏色分別給了1 2 3 4)
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)

字符矩陣:
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)

如您所見,對于數(shù)值矩陣(無論是連續(xù)映射還是離散映射),默認(rèn)情況下在兩個維度上都使用聚類,而對于字符矩陣,則不使用聚類。
NA值允許出現(xiàn)在heatmap中.你可以通過na_col 參數(shù)為NA設(shè)定顏色. 包含 NA的矩陣也可以被 Heatmap()聚類 (因為 dist() 支持 NA值) and 使用 “pearson”, “spearman” or “kendall” 方法聚類帶有NA值的矩陣將引出warning messages.
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.

顏色空間對于插入顏色是很重要的.默認(rèn)情況下, colors 是在LAB color space線性分布的, 但是你也可以通過colorRamp2() 函數(shù)選擇color space. 對比下方兩圖 (兩張圖的+ 操作會在[Making a list of heatmaps]中被介紹)
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 包畫的)對應(yīng)的值在折疊軸上均勻變化. 選擇一個合適的顏色空間是有點主觀的,這取決于具體的數(shù)據(jù)和顏色主題,有時候你需要嘗試多種顏色空間,來最終選的一種可以最好展示數(shù)據(jù)結(jié)構(gòu)的顏色空間


Titles 標(biāo)題
熱圖的name默認(rèn)情況下被用作熱圖圖例的標(biāo)題。如果你同時繪制多個熱圖,這名字也可以作為唯一的id。稍后,我們可以使用這個名稱到相應(yīng)的熱圖中添加更多的圖形 (具體看[Heatmap Decoration]vignette).
Heatmap(mat, name = "foo")

你可以使用heatmap_legend_param修改熱圖圖例的標(biāo)題(具體見 [Heatmap and Annotation Legends]vignette 獲得更多對圖庫的控制).
Heatmap(mat, heatmap_legend_param = list(title = "legend"))

您可以將熱圖標(biāo)題設(shè)置為按行或按列放置。同時注意,你只能把列標(biāo)題放在熱圖的頂部或底部。圖形參數(shù)可以分別由' row_title_gp '和' column_title_gp '設(shè)置。請記住您應(yīng)該使用"gpar()"來指定圖形參數(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 column title at the bottom",
column_title_side = "bottom")

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

標(biāo)題的旋轉(zhuǎn)可以通過' row_title_rot '和' column_title_rot '設(shè)置,但只允許水平和垂直旋轉(zhuǎn)。
Heatmap(mat, name = "foo", row_title = "row title", row_title_rot = 0)

Clustering 聚類
You can specify the clustering either by a pre-defined method (e.g. “eulidean” or “pearson”), or by a distance function, or by a object that already contains clustering, or directly by a clustering function. It is also possible to render your dendrograms with different colors and styles for different branches for better revealing structures of your data.
First there are general settings for the clustering, e.g. whether do or show dendrograms, side of the dendrograms and size of the dendrograms.
聚類是熱圖可視化的關(guān)鍵特性。在ComplexHeatmap包中, 聚類有很高的靈活性. 你可以通過預(yù)定的方法來指定聚類方法如(e.g. “eulidean” or “pearson”), 或者使用距離函數(shù), or by a object that already contains clustering,or directly by a clustering function. 還可以為不同的分支呈現(xiàn)不同顏色和樣式的樹狀圖,以便更好地顯示數(shù)據(jù)結(jié)構(gòu)。
首先是聚類的的一般設(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"))

這里提供三種方法指定聚類的距離度量:
- 將距離指定為預(yù)定義選項(specify distance as a pre-defined option). 預(yù)定義選項可用的值是
dist()函數(shù)中支持的方法和pearson,spearmanandkendall.NA值在預(yù)定義選項的聚類中是被忽略的但會拋出 warnings (see example in Colors section). - 一個自定義函數(shù),從矩陣計算距離。函數(shù)應(yīng)該只包含一個參數(shù)。請注意,對于列的聚類,矩陣將自動transposed 。
- 一個自定義函數(shù),計算兩個向量之間的距離。函數(shù)應(yīng)該只包含兩個參數(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))

基于該特征,我們可以利用對異常值魯棒性強的聚類方法應(yīng)用于配對距離(the pair-wise distance.)
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)

如果提供了可用的距離方法,還可以對字符矩陣進行聚類?!癱ell_fun”參數(shù)將在后面的小節(jié)中解釋。
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)
})

可以通過' clustering_method_rows '和' clustering_method_columns '指定實現(xiàn)分層聚類的方法。可用的方法是' hclust() '函數(shù)中支持的方法。
Heatmap(mat, name = "foo", clustering_method_rows = "single")

默認(rèn)情況下,聚類由' hclust() '執(zhí)行。但是您也可以通過將“cluster_rows”或“cluster_columns”指定為“hclust”或“dendrogram”對象來利用其他方法生成的聚類結(jié)果。在下面的示例中,我們使用來自cluster包的' diana() '和' agnes() '方法來執(zhí)行聚類。
library(cluster)
Heatmap(mat, name = "foo", cluster_rows = as.dendrogram(diana(mat)),
cluster_columns = as.dendrogram(agnes(t(mat))))

在原生的“heatmap()”函數(shù)中,行和列上的樹狀圖被重新排序,以便將差異較大的特性彼此分隔開來,默認(rèn)情況下,對樹木圖的重新排序也可由“heatmap()”打開。
除了默認(rèn)的重新排序方法之外,您還可以先生成一個樹形圖并應(yīng)用其他重新排序方法,然后將重新排序的樹形圖發(fā)送給' cluster_rows '參數(shù).
對比以下三個圖:
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包來呈現(xiàn)您的“樹狀圖”對象,并對樹狀圖進行更自定義的可視化。
library(dendextend)
dend = hclust(dist(mat))
dend = color_branches(dend, k = 2)
Heatmap(mat, name = "foo", cluster_rows = dend)

通常cluster_rows 和 cluster_columns can be 聚類的函數(shù). 自定義函數(shù)的輸入?yún)?shù)應(yīng)該是一個矩陣,返回值應(yīng)該是hclust or dendrogram對象. 請注意當(dāng) cluster_rows 在內(nèi)部被執(zhí)行時 參數(shù) m 就是你的輸入 mat而在執(zhí)行cluster_columns時m 是mat的轉(zhuǎn)置 .
Heatmap(mat, name = "foo", cluster_rows = function(m) as.dendrogram(diana(m)),
cluster_columns = function(m) as.dendrogram(agnes(m)))

' fastcluster::hclust '是' hclust '的更快版本。我們可以重新定義' cluster_rows '和' cluster_columns '來使用' hclust '的更快版本。但是請注意“fastcluster::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è)您有許多熱圖要連接),你可以將設(shè)置為一個全局選項:
# 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)整行和列中的順序。但您仍然可以通過' row_order '和' column_order '手動設(shè)置順序。注意,如果想手動設(shè)置順序,需要 turn off clustering?!皉ow_order”和“column_order”也可以根據(jù)存在的矩陣行名和列名設(shè)置。
Heatmap(mat, name = "foo", cluster_rows = FALSE, cluster_columns = FALSE,
row_order = 12:1, column_order = 10:1)

注意“row_dend_reorder”和“row_order”是不同的。' row_dend_reorder '應(yīng)用于樹狀圖。因為對于樹形圖中的任何節(jié)點,旋轉(zhuǎn)兩片葉子會得到相同的樹形圖。因此,通過在每個節(jié)點上自動旋轉(zhuǎn)子樹狀圖來重新排序樹狀圖,將有助于將差異較大的元素分離開來,使它們之間的距離更遠(yuǎn)。當(dāng)' row_order '應(yīng)用于矩陣時和樹狀圖的該功能會被抑制。
Dimension names 維度名稱
維度名稱的邊、可見性和圖形參數(shù)可以設(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))))

目前,不支持對列名和行名進行旋轉(zhuǎn)(或者可能在將來的版本中實現(xiàn)該功能)。因為在文本旋轉(zhuǎn)之后,維度名稱將進入其他熱圖組件,這將打亂熱圖布局。但是,正如將在[Heatmap Annotation] vignette中介紹的,在Heatmap注釋中允許文本旋轉(zhuǎn)。因此,用戶可以提供一個只包含旋轉(zhuǎn)文本的行注釋或列注釋來模擬旋轉(zhuǎn)的行/列名稱 (Y你可以看 [Heatmap Annotation]中的例子).
Split heatmap by rows 按行分割熱圖
熱圖可以按行分割。這將增強熱圖中組分離的可視化。值大于1的“km”參數(shù)表示對行進行k-means聚類,并且集群應(yīng)用于每個k-means集群. clustering is applied on every k-means cluster.--設(shè)置km值,按行分割
Heatmap(mat, name = "foo", km = 2)

通常,split可以設(shè)置為向量或數(shù)據(jù)框(dataframe),它們被用于不同程度的組合分割heatmap的行。實際上,k-means聚類只是生成一個行類的向量,并給split附加一個額外的列。每個行slice的組合行標(biāo)題可以由combined_name_fun參數(shù)控制。每個slice的順序可以由split中每個變量的levels控制。--"其實就是按行分割,并給分割的組命名"
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 partitioning method不滿意,那么只需將分區(qū)向量(partitioning vector)分配給"split",就可以輕松地使用其他partitioning methods.
pa = pam(mat, k = 3)
Heatmap(mat, name = "foo", split = paste0("pam", pa$clustering))

如果設(shè)置了row_order, 在每個slice中,行仍然是有序的。--就是分片完,每片片內(nèi)的順序和row_order一致
Heatmap(mat, name = "foo", row_order = 12:1, cluster_rows = FALSE, km = 2)

row slices之間間隙的高度可以由gap控制。 (a single unit or a vector of units).--設(shè)置間隔高度
Heatmap(mat, name = "foo", split = paste0("pam", pa$clustering), gap = unit(5, "mm"))

字符矩陣只能被"split"參數(shù)分割.
Heatmap(discrete_mat, name = "foo", col = 1:4,
split = rep(letters[1:2], each = 5))

當(dāng)split 應(yīng)用于行時,row title and row names的graphic parameters可以指定為與row slices數(shù)量相同的長度.
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)有了行的樹狀圖,他們希望通過將樹狀圖分割成k個子樹來分割行。 在這種情況下,split可以指定為a single number:
dend = hclust(dist(mat))
dend = color_branches(dend, k = 2)
Heatmap(mat, name = "foo", cluster_rows = dend, split = 2)

或者他們只是通過為split指定整數(shù)來拆分行。 注意它與km不同。 如果設(shè)置了“km”,則首先應(yīng)用k均值聚類,并將聚類應(yīng)用于每個k均值簇; 而如果split是一個整數(shù),則將聚類應(yīng)用于整個矩陣,然后通過cutree()進行分割。
Heatmap(mat, name = "foo", split = 2)

Self define the heatmap body自定義熱圖主體部分
參數(shù)"rect_gp"為熱圖主體提供了基本的圖形設(shè)置(注意,"fill"參數(shù)是不可用的)。
Heatmap(mat, name = "foo", rect_gp = gpar(col = "green", lty = 2, lwd = 2))

默認(rèn)情況下,熱圖主體是可被自定義的。熱圖主體由一組具有不同的填充顏色的rectangles(it is called cells here)組成。如果rect_gp中的type設(shè)置為none,則會初始化單元格數(shù)組,但不會放入任何圖形。然后,用戶可以通過cell_fun定義自己的圖形函數(shù)。 cell_fun應(yīng)用于熱圖中的每個單元格,并提供有關(guān)'current'單元格的以下信息:
-
j: 列號. 列索引對應(yīng)于視圖中的x方向,這就是為什么將“j”作為第一個參數(shù). -
i: 行號. -
x: x coordinate of middle point of the cell which is measured in the viewport of the heatmap body.在heatmap主題體的視區(qū)中測量的單元中點的X坐標(biāo)。 -
y: y coordinate of middle point of the cell which is measured in the viewport of the heatmap body. -
width: cell的寬度. -
height: cell的高度. -
fill: cell的顏色.
最常見的用法是向熱圖添加數(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))
})

在下面的例子中,我們制作了一個heatmap,它展示了相關(guān)性矩陣(類似于corrplot包):
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)

注cell_fun是通過for循環(huán)應(yīng)用于每個單元格,因此大型矩陣的速度會慢一點.
最后一個例子是可視化一個GO game。輸入數(shù)據(jù)是記錄的游戲中的動作。
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)換成一個矩陣:
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
黑色和白色的stones是根據(jù)矩陣中的值放置的:
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")
)

Set heatmap body as raster image 將heatmap主體設(shè)置為raster image
以PDF格式保存繪圖是保持質(zhì)量的最佳方法。但是,當(dāng)行太多(例如,大于10000行)時,輸出的PDF文件大小將非常大,讀取繪圖需要時間和內(nèi)存。 另一方面,在有限大小的PDF文件中看不到巨大矩陣的細(xì)節(jié)。將heatmap渲染為raster images將有效地減小文件大小。在heatmap()函數(shù)中,有四個選項控制如何生成raster images: use_raster, raster_device, raster_quality, raster_device_param.
您可以通過raster_device選擇graphic device(png、jpeg和tiff),并通過raster_quality參數(shù)控制raster image的質(zhì)量,并通過' raster_device_param '為特定的device傳遞參數(shù)。 Check this web page for better demonstrations.
Session info
sessionInfo()
## R version 3.5.1 Patched (2018-07-24 r75008)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows Server 2012 R2 x64 (build 9600)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=C LC_CTYPE=English_United States.1252
## [3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C
## [5] LC_TIME=English_United States.1252
##
## 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