🎨[可视化|R包]ComplexHeatmap学习笔记②Making A Single Heatmap

  1. ComplexHeatmap学习笔记①Introduction to ComplexHeatmap package

Making A Single Heatmap


单热图(A single heatmap):主要用于快速查看数据。这是heatmap list的一个特例,它只包含一个热图。与现有工具相比,ComplexHeatmap包提供了更灵活的方法来支持单个heatmap的可视化。在下面的示例中,我们将演示如何设置参数来可视化单个热图。

加载包,生成一个随机矩阵--(用于测试):

library(ComplexHeatmap)
library(circlize)

set.seed(123) #郑宝童简书上,提供了一个关于set.seed()函数的解析

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)

用默认设置绘制热图。热图的默认样式与其他相似的热图函数生成的样式非常相似。

Heatmap(mat)
默认设置绘图

Colors颜色

colorRamp2()的两个参数分别是截断值和相对应的颜色. 当前colorRamp2() 通过LAB color space在每个间隔中线性插入颜色。

在大多数情况下,热图可视化的是具有连续值的矩阵。 在这种情况下,用户应提供颜色映射功能。 颜色映射函数是输入值向量返回颜色向量的函数。 ** circlize **包中的colorRamp2()有助于生成这些函数。colorRamp2()有两个参数是:包含截断值和相应颜色的向量。
下方例子中, -3到3之间的值通过线性分布以获得相应的颜色, > 3:red ;< -3:green (所以这里演示的颜色映射函数对异常值也是稳定可用的).--colorRamp2设置颜色

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

如果矩阵是连续的,您还可以提供颜色向量,颜色将根据'k'分位数进行插值。 但请记住,这种方法对异常值并不稳健。

Heatmap(mat, col = rev(rainbow(10)))
image.png

如果矩阵包含离散值(数字或字符),则应将颜色指定给命名向量,以使从离散值映射到颜色成为可能。如果没为颜色指定命名向量, 颜色顺序对应于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)
字符

如您所见,对于数值矩阵(无论是连续映射还是离散映射),默认情况下在两个维度上都使用聚类,而对于字符矩阵,则不使用聚类。

NA值允许出现在heatmap中.你可以通过na_col 参数为NA设定颜色. 包含 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.
聚类

颜色空间对于插入颜色是很重要的.默认情况下, colors 是在LAB color space线性分布的, 但是你也可以通过colorRamp2() 函数选择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")
image

下图中,可以看到不同颜色空间下的颜色变化 (这些图是 HilbertCurve 包画的)对应的值在折叠轴上均匀变化. 选择一个合适的颜色空间是有点主观的,这取决于具体的数据和颜色主题,有时候你需要尝试多种颜色空间,来最终选的一种可以最好展示数据结构的颜色空间

1

2

Titles 标题

热图的name默认情况下被用作热图图例的标题。如果你同时绘制多个热图,这名字也可以作为唯一的id。稍后,我们可以使用这个名称到相应的热图中添加更多的图形 (具体看[Heatmap Decoration]vignette).

Heatmap(mat, name = "foo")
name

你可以使用heatmap_legend_param修改热图图例的标题(具体见 [Heatmap and Annotation Legends]vignette 获得更多对图库的控制).

Heatmap(mat, heatmap_legend_param = list(title = "legend"))
修改图例标题

您可以将热图标题设置为按行或按列放置。同时注意,你只能把列标题放在热图的顶部或底部。图形参数可以分别由' row_title_gp '和' column_title_gp '设置。请记住您应该使用"gpar()"来指定图形参数。

Heatmap(mat, name = "foo", column_title = "I am a column title", 
    row_title = "I am a row title")
row_title
Heatmap(mat, name = "foo", column_title = "I am a column title at the bottom", 
    column_title_side = "bottom")
column_title
Heatmap(mat, name = "foo", column_title = "I am a big column title", 
    column_title_gp = gpar(fontsize = 20, fontface = "bold"))
指定图形参数

标题的旋转可以通过' row_title_rot '和' column_title_rot '设置,但只允许水平和垂直旋转。

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.
聚类是热图可视化的关键特性。在ComplexHeatmap包中, 聚类有很高的灵活性. 你可以通过预定的方法来指定聚类方法如(e.g. “eulidean” or “pearson”), 或者使用距离函数, or by a object that already contains clustering,or directly by a clustering function. 还可以为不同的分支呈现不同颜色和样式的树状图,以便更好地显示数据结构。
首先是聚类的的一般设置,例如是否做或显示树状图、树状图的边和树状图的大小。

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"))
设置树状图高度

这里提供三种方法指定聚类的距离度量:

  • 将距离指定为预定义选项(specify distance as a pre-defined option). 预定义选项可用的值是dist()函数中支持的方法和pearson, spearman and kendall. NA 值在预定义选项的聚类中是被忽略的但会抛出 warnings (see example in Colors section).
  • 一个自定义函数,从矩阵计算距离。函数应该只包含一个参数。请注意,对于列的聚类,矩阵将自动transposed 。
  • 一个自定义函数,计算两个向量之间的距离。函数应该只包含两个参数.
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))
自定义函数

基于该特征,我们可以利用对异常值鲁棒性强的聚类方法应用于配对距离(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)

鲁棒性

如果提供了可用的距离方法,还可以对字符矩阵进行聚类。“cell_fun”参数将在后面的小节中解释。

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 '指定实现分层聚类的方法。可用的方法是' hclust() '函数中支持的方法。

Heatmap(mat, name = "foo", clustering_method_rows = "single")
指定聚类方法

默认情况下,聚类由' hclust() '执行。但是您也可以通过将“cluster_rows”或“cluster_columns”指定为“hclust”或“dendrogram”对象来利用其他方法生成的聚类结果。在下面的示例中,我们使用来自cluster包的' diana() '和' agnes() '方法来执行聚类。

library(cluster)
Heatmap(mat, name = "foo", cluster_rows = as.dendrogram(diana(mat)),
   cluster_columns = as.dendrogram(agnes(t(mat))))
指定执行聚类的函数

在原生的“heatmap()”函数中,行和列上的树状图被重新排序,以便将差异较大的特性彼此分隔开来,默认情况下,对树木图的重新排序也可由“heatmap()”打开。

除了默认的重新排序方法之外,您还可以先生成一个树形图并应用其他重新排序方法,然后将重新排序的树形图发送给' cluster_rows '参数.

对比以下三个图:

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包来呈现您的“树状图”对象,并对树状图进行更自定义的可视化。

library(dendextend)
dend = hclust(dist(mat))
dend = color_branches(dend, k = 2)
Heatmap(mat, name = "foo", cluster_rows = dend)
对树状图自定义

通常cluster_rowscluster_columns can be 聚类的函数. 自定义函数的输入参数应该是一个矩阵,返回值应该是hclust or dendrogram对象. 请注意当 cluster_rows 在内部被执行时 参数 m 就是你的输入 mat而在执行cluster_columnsmmat的转置 .

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
fastcluster::hclust

为了更方便地使用快版本的“hclust”(假设您有许多热图要连接),你可以将设置为一个全局选项:

# 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")
fast_hclust

聚类可以帮助调整行和列中的顺序。但您仍然可以通过' row_order '和' column_order '手动设置顺序。注意,如果想手动设置顺序,需要 turn off clustering。“row_order”和“column_order”也可以根据存在的矩阵行名和列名设置。

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 '应用于树状图。因为对于树形图中的任何节点,旋转两片叶子会得到相同的树形图。因此,通过在每个节点上自动旋转子树状图来重新排序树状图,将有助于将差异较大的元素分离开来,使它们之间的距离更远。当' row_order '应用于矩阵时和树状图的该功能会被抑制。

Dimension names 维度名称

维度名称的边、可见性和图形参数可以设置如下。

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))))
设置字体颜色

目前,不支持对列名和行名进行旋转(或者可能在将来的版本中实现该功能)。因为在文本旋转之后,维度名称将进入其他热图组件,这将打乱热图布局。但是,正如将在[Heatmap Annotation] vignette中介绍的,在Heatmap注释中允许文本旋转。因此,用户可以提供一个只包含旋转文本的行注释或列注释来模拟旋转的行/列名称 (Y你可以看 [Heatmap Annotation]中的例子).

Split heatmap by rows 按行分割热图

热图可以按行分割。这将增强热图中组分离的可视化。值大于1的“km”参数表示对行进行k-means聚类,并且集群应用于每个k-means集群. clustering is applied on every k-means cluster.--设置km值,按行分割

Heatmap(mat, name = "foo", km = 2)
热图按行分割

通常,split可以设置为向量或数据框(dataframe),它们被用于不同程度的组合分割heatmap的行。实际上,k-means聚类只是生成一个行类的向量,并给split附加一个额外的列。每个行slice的组合行标题可以由combined_name_fun参数控制。每个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)
按行分割,并为分组命名

如果您对默认的k-means partitioning method不满意,那么只需将分区向量(partitioning vector)分配给"split",就可以轻松地使用其他partitioning methods.

pa = pam(mat, k = 3)
Heatmap(mat, name = "foo", split = paste0("pam", pa$clustering))
其他分区方法

如果设置了row_order, 在每个slice中,行仍然是有序的。--就是分片完,每片片内的顺序和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).--设置间隔高度

Heatmap(mat, name = "foo", split = paste0("pam", pa$clustering), gap = unit(5, "mm"))
设置间隔高度

字符矩阵只能被"split"参数分割.

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

当split 应用于行时,row title and row names的graphic parameters可以指定为与row slices数量相同的长度.

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)))
自定义行标题和行名

用户可能已经有了行的树状图,他们希望通过将树状图分割成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指定一个数字

或者他们只是通过为split指定整数来拆分行。 注意它与km不同。 如果设置了“km”,则首先应用k均值聚类,并将聚类应用于每个k均值簇; 而如果split是一个整数,则将聚类应用于整个矩阵,然后通过cutree()进行分割。

Heatmap(mat, name = "foo", split = 2)
split设置数字

Self define the heatmap body自定义热图主体部分

参数"rect_gp"为热图主体提供了基本的图形设置(注意,"fill"参数是不可用的)。

Heatmap(mat, name = "foo", rect_gp = gpar(col = "green", lty = 2, lwd = 2))
自定义主体部分

默认情况下,热图主体是可被自定义的。热图主体由一组具有不同的填充颜色的rectangles(it is called cells here)组成。如果rect_gp中的type设置为none,则会初始化单元格数组,但不会放入任何图形。然后,用户可以通过cell_fun定义自己的图形函数。 cell_fun应用于热图中的每个单元格,并提供有关'current'单元格的以下信息:

  • j: 列号. 列索引对应于视图中的x方向,这就是为什么将“j”作为第一个参数.
  • i: 行号.
  • x: x coordinate of middle point of the cell which is measured in the viewport of the heatmap body.在heatmap主题体的视区中测量的单元中点的X坐标。
  • 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的颜色.

最常见的用法是向热图添加数值:

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,它展示了相关性矩阵(类似于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循环应用于每个单元格,因此大型矩阵的速度会慢一点.

最后一个例子是可视化一个GO game。输入数据是记录的游戏中的动作。

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]"

然后我们把它转换成一个矩阵:

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是根据矩阵中的值放置的:

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")
)
GO game

Set heatmap body as raster image 将heatmap主体设置为raster image

以PDF格式保存绘图是保持质量的最佳方法。但是,当行太多(例如,大于10000行)时,输出的PDF文件大小将非常大,读取绘图需要时间和内存。 另一方面,在有限大小的PDF文件中看不到巨大矩阵的细节。将heatmap渲染为raster images将有效地减小文件大小。在heatmap()函数中,有四个选项控制如何生成raster images: use_raster, raster_device, raster_quality, raster_device_param.

您可以通过raster_device选择graphic device(pngjpegtiff),并通过raster_quality参数控制raster image的质量,并通过' raster_device_param '为特定的device传递参数。 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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容