其它高级图
参考链接
1.密度热图
我们通常使用箱线图或小提琴图可视化矩阵或列表中的数据,。我们还可以使用颜色来映射密度值并通过热图可视化分布。如果您有大量数据要可视化,这将非常有用。
在以下示例中,我们使用矩阵作为输入数据,其中密度按列计算。输入数据也可以是一个列表。
set.seed(123)
m = cbind(matrix(rnorm(10*100), ncol = 10),
matrix(runif(10*100, min = -2, max = 2) + 0.5, ncol = 10))
colnames(m) = paste0("C", 1:ncol(m))
densityHeatmap(m)
在热图上,还有五个分位数和平均值的线条。
数据范围由ylim
控制。标题由title
或column_title
控制。y 轴上的标题由ylab
控制。
densityHeatmap(m, ylim = c(-2, 2), title = "Distribution as heatmap", ylab = "some values")
列顺序由column_order
控制。
densityHeatmap(m, column_order = sample(20, 20))
密度值的颜色由col
控制,col
是一个向量。
densityHeatmap(m, col = topo.colors(10))
在内部,所有列的密度都存储为一个矩阵,其中行对应于相同的 bin。由于它是一个矩阵,因此可以对其应用聚类。有一种特殊的距离方法ks
用于测量分布之间的相似性,即两个分布之间的 Kolmogorov-Smirnov 统计量(如果 cluster_column = TRUE
,则ks
距离是默认值)。
densityHeatmap(m, cluster_columns = TRUE, clustering_distance_columns = "ks")
当有许多分布来计算成对 Kolmogorov-Smirnov 距离时, 为提高运行速度,设置mc.cores
参数可以并行运行。
densityHeatmap(m, cluster_columns = TRUE, mc.cores = ...)
列注释可以添加为顶部注释或底部注释。
ha1 = HeatmapAnnotation(dist = c(rep("rnorm", 10), rep("runif", 10)))
ha2 = HeatmapAnnotation(foo = anno_points(rnorm(20)))
densityHeatmap(m, top_annotation = ha1, bottom_annotation = ha2)
热图和列注释只能垂直连接到密度热图。
densityHeatmap(m) %v%
HeatmapAnnotation(foo = anno_barplot(1:20)) %v%
Heatmap(matrix(rnorm(20*20), ncol = 20), name = "mat", height = unit(6, "cm"))
还有一个frequencyHeatmap()
函数类似于密度热图的直方图版本。用法类似于densityHeatmap()
:
frequencyHeatmap(m)
2. 堆叠图
多个注释和热图可用于可视化同一组特征的多个汇总统计数据。在以下示例中,有来自四个不同亚组的差异甲基化区域 (DMR) 的多个统计数据。
lt = readRDS(system.file("extdata", package = "ComplexHeatmap", "dmr_summary.rds"))
names(lt)
## [1] "label" "mean_meth" "n_gr" "n_corr"
## [5] "dist_tss" "gene_anno" "cgi_anno" "mat_enrich_gf"
## [9] "mat_pct_st" "mat_enrich_st"
这些 DMR 的统计数据是:
-
label
:DMR 集的标签。有四个亚组的 DMR,对于每个亚组,DMR 分为高甲基化 DMR 和低甲基化 DMR。 -
mean_meth
:肿瘤样品和正常样品中 DMR 的平均甲基化。 -
n_gr
每组 DMR 的数量。 -
n_corr
:显示与附近基因显着相关的 DMR 的百分比。分别计算正相关和负相关。 -
dist_tss
:与附近基因 TSS 的距离。该值是当前集合中距离小于 1kb、1kb-5kb、5kb-10kb 以及大于 10kb 的 DMR 的比例。 -
gene_anno
:与基因或基因间区域重叠的 DMR 的比例。 -
cgi_anno
:与 CpG 岛或 CGI 岛重叠的 DMR 的比例。 -
mat_enrich_gf
:对基因组特征列表的丰度。正值意味着过度代表。 -
mat_pct_st
:与染色质状态重叠的 DMR 的比例。 -
mat_enrich_st
:染色质状态的富集。
将所有这些变量附加到工作环境中。
attach(lt)
由于我们有许多统计数据需要可视化,我们首先定义颜色。我们为要可视化为热图的统计数据定义颜色映射函数,并为要可视化为条形图的统计数据定义颜色映射函数。
library(circlize)
meth_col_fun = colorRamp2(c(0, 0.5, 1), c("blue", "white", "red"))
corr_col = c("green", "red")
dist_tss_col = c("#FF0000", "#FF7352", "#FFB299", "#FFD9CB")
gene_anno_col = c("green", "blue")
cgi_anno_col = c("#FFA500", "#FFD191")
z_score_col_fun = colorRamp2(c(-200, 0, 200), c("green", "white", "red"))
state_col = c("#FF0000", "#008000", "#C2E105", "#8A91D0", "#CD5C5C", "#808080", "#000000")
热图列表的构建非常简单。每个统计数据都被构造为热图或行注释。
anno_width = unit(3, "cm")
ht_list = rowAnnotation(text = anno_text(label, location = unit(1, "npc"), just = "right",
gp = gpar(fontsize = 12)))
ht_list = ht_list + Heatmap(mean_meth, name = "mean_meth", col = meth_col_fun,
cluster_rows = FALSE, row_title = NULL, cluster_columns = FALSE, show_row_names = FALSE,
heatmap_legend_param = list(title = "Methylation"), width = ncol(mean_meth)*unit(4, "mm")) +
rowAnnotation("n_gr" = anno_barplot(n_gr, bar_width = 1, width = anno_width),
show_annotation_name = FALSE) +
rowAnnotation("n_corr" = anno_barplot(n_corr, bar_width = 1, gp = gpar(fill = corr_col),
width = anno_width), show_annotation_name = FALSE) +
rowAnnotation("dist_tss" = anno_barplot(dist_tss, bar_width = 1, gp = gpar(fill = dist_tss_col),
width = anno_width), show_annotation_name = FALSE) +
rowAnnotation("gene_anno" = anno_barplot(gene_anno, bar_width = 1, gp = gpar(fill = gene_anno_col),
width = anno_width), show_annotation_name = FALSE) +
rowAnnotation("cgi_anno" = anno_barplot(cgi_anno, bar_width = 1, gp = gpar(fill = cgi_anno_col),
width = anno_width), show_annotation_name = FALSE) +
Heatmap(mat_enrich_gf, name = "enrich_gf", col = z_score_col_fun, cluster_columns = FALSE,
width = unit(ncol(mat_enrich_gf)*4, "mm"), column_title = "",
heatmap_legend_param = list(title = "Z-score")) +
rowAnnotation("pct_st" = anno_barplot(mat_pct_st, bar_width = 1, gp = gpar(fill = state_col),
width = anno_width), show_annotation_name = FALSE) +
Heatmap(mat_enrich_st, name = "enrich_st", col = z_score_col_fun, cluster_columns = FALSE,
width = unit(ncol(mat_enrich_st)*6, "mm"), column_title = "", show_heatmap_legend = FALSE,
column_names_gp = gpar(col = state_col), show_row_names = FALSE)
由于注释条形图不生成图例,我们使用Legend()
函数手动构建这些图例。
lgd_list = list(
Legend(labels = c("gene", "intergenic"), title = "Gene annotation",
legend_gp = gpar(fill = gene_anno_col)),
Legend(labels = c("<1kb", "1kb~5kb", "5kb~10kb", ">10kb"), title = "Distance to TSS",
legend_gp = gpar(fill = dist_tss_col)),
Legend(labels = c("CGI", "CGI shore"), title = "CGI annotation",
legend_gp = gpar(fill = cgi_anno_col)),
Legend(labels = colnames(mat_enrich_st), title = "Chromatin states",
legend_gp = gpar(fill = state_col))
)
在绘制热图列表时,所有热图和注释的行被分为两大组。注意在Heatmap()
对应于平均甲基化矩阵的第一个中,我们设置 row_title = NULL
删除来自行拆分的行标题。
由于稍后我们将为注释添加标题,因此我们通过padding
参数在整个绘图区域的顶部分配空白。此外,我们将自定义图例列表连接到热图图例列表,并将它们水平放置在热图列表的底部。
draw(ht_list, padding = unit(c(2, 2, 20, 2), "mm"), row_split = gsub("\\d+$", "", label),
heatmap_legend_list = lgd_list, heatmap_legend_side = "bottom")
anno_title = c("n_gr" = "Number of\nDMRs", "n_corr" = "Significantly\ncorrelated genes",
"gene_anno" = "Gene annotation", "dist_tss" = "Distance to TSS",
"cgi_anno" = "CGI annotation", "pct_st" = "Overlap to\nChromatin states")
for(an in names(anno_title)) {
decorate_annotation(an, {
grid.text(anno_title[an], y = unit(1, "npc") + unit(3, "mm"), just = "bottom")
})
}
ht_title = c("mean_meth" = "Mean\nmethylation", "enrich_gf" = "Enrichment to\ngenomic features",
"enrich_st" = "Enrichment to\nchromatin states")
for(an in names(ht_title)) {
decorate_heatmap_body(an, {
grid.text(ht_title[an], y = unit(1, "npc") + unit(3, "mm"), just = "bottom")
})
}
同样,多个统计量也可以垂直排列。在以下示例中,我们将来自四个子组的 40 个样本中的基因组区域列表的多个统计数据可视化。统计数据如下:
-
prop
: 基因组中的比例。 -
median_length
:每个样本中区域的中位数长度。 -
group
: 子组标签。
prop = c(
runif(10, min = 0.1, max = 0.5),
runif(10, min = 0.2, max = 0.4),
runif(10, min = 0.3, max = 0.6),
runif(10, min = 0.4, max = 0.8)
)
median_length = c(
runif(10, min = 5000, max = 10000),
runif(10, min = 6000, max = 20000),
runif(10, min = 7000, max = 15000),
runif(10, min = 6000, max = 30000)
)
group = rep(letters[1:4], each = 10)
请注意,在以下示例中,列表中没有热图。
ht_list = HeatmapAnnotation(prop = anno_barplot(prop, height = unit(4, "cm"),
axis_param = list(at = c(0, 0.2, 0.4, 0.6, 0.8),
labels = c("0%", "20%", "40%", "60%", "80%"))),
annotation_name_rot = 90) %v%
HeatmapAnnotation(median_length = anno_barplot(median_length, height = unit(4, "cm"),
axis_param = list(at = c(0, 10000, 20000), labels = c("0kb", "10kb", "20kb"))),
annotation_name_rot = 90) %v%
HeatmapAnnotation(group = group)
draw(ht_list, column_title = "Statistics for a list of genomic regions")
对于多个注释的串联,也可以将单个注释放入一个 HeatmapAnnotation()
. 例如,之前的代码与以下代码几乎完全相同:
# code only for demonstration
HeatmapAnnotation(
prop = anno_barplot(prop, height = unit(4, "cm"),
axis_param = list(at = c(0, 0.2, 0.4, 0.6, 0.8),
labels = c("0%", "20%", "40%", "60%", "80%"))),
median_length = anno_barplot(median_length, height = unit(4, "cm"),
axis_param = list(at = c(0, 10000, 20000), labels = c("0kb", "10kb", "20kb"))),
group = group,
annotation_name_rot = c(90, 90, 0),
gap = unit(2, "mm")
) %v% NULL # add NULL to convert single HeatmapAnnotation to HeatmapList
三维热图
参考链接
1.motivation
ComplexHeatmap具有densityHeatmap()
可视化密度分布列表,例如在以下示例中:
library(ComplexHeatmap)
set.seed(123)
mat = matrix(rnorm(500), ncol = 10)
colnames(mat) = letters[1:10]
densityHeatmap(mat)
在基本的 R 图形中,由于分布也可以通过直方图进行可视化,因此从ComplexHeatmap 版本 2.7.9 开始,添加了一个新函数frequencyHeatmap()
,类似于密度热图的直方图版本。用法类似于densityHeatmap()
:
frequencyHeatmap(mat)
在前面的示例中,频率矩阵被可视化为热图。注意:frequencyHeatmap()
可以使用不同的统计,即,"count"
,"proportion"
或"density"
。
由于频率热图声称是密度热图的直方图版本,但它看起来根本不像直方图。也许带有 3D 条的 3D 热图更合适。这可以在frequencyHeatmap()
使用use_3d = TRUE
.
frequencyHeatmap(mat, use_3d = TRUE)
接下来,将解释 3D 热图是如何实现的。
2. 3D热图的实现
首先,需要绘制 3D 条。这可以通过新函数来完成bar3D()
。用法如下:
bar3D(x = 0.5, y = 0.5, w = 0.2, h = 0.2, l = unit(1, "cm"), theta = 60)
论据是:
-
x
:底面中心点的x坐标。值应该是一个unit
对象。如果是数字,则默认单位为npc
。 -
y
:底面中心点的y坐标。 -
w
:条的宽度(在 x 方向)。请参见下图。 -
h
:条的高度(在 y 方向)。请参见下图。 -
l
:钢筋的长度(在 z 方向)。请参见下图。 -
theta
:投影的角度。请参见下图。注意theta
只能取 0 到 90 之间的值。
为了增强 3D 可视化的视觉效果,可以通过fill
参数设置颜色。
bar3D(x = seq(0.2, 0.8, length = 4), y = 0.5, w = unit(5, "mm"), h = unit(5, "mm"),
l = unit(1, "cm"), fill = c("red", "green", "blue", "purple"))
theta
参数设置投影的角度,theta
只能取 0 到 90 之间的值。
bar3D(x = seq(0.2, 0.8, length = 4), y = 0.5, w = unit(5, "mm"), h = unit(5, "mm"),
l = unit(1, "cm"), theta = c(20, 40, 60, 80))
要将条形添加到热图的每个单元,我们可以简单地在将每个条形bar3D()
添加到每个单元格的位置cell_fun
或layer_fun
位置中实现。通过 Heatmap3D()
可以简化这一操作。Heatmap3D()
接受几乎所有的参数,Heatmap()
唯一的区别是每个单元格都有一个 3D 条,其高度对应于它的值。
Heatmap3D()
只允许非负矩阵作为输入。默认值也是一些参数的更改,例如行名称放在热图的左侧,仍然应用聚类,但默认情况下不绘制树状图。
以下是使用的演示Heatmap3D()
:
set.seed(7)
mat = matrix(runif(100), 10)
rownames(mat) = LETTERS[1:10]
colnames(mat) = letters[1:10]
Heatmap3D(mat, name = "mat", column_title = "This is a 3D heatmap")
在前面的例子中,如果靠近热图顶部或热图右侧的条形长度过大,它们将与热图标题或图例重叠,在这种情况下,我们需要手动调整它们之间的间距,例如,标题和主体热图。
在ComplexHeatmap 中,有几个全局选项可以控制热图组件之间的空间。为了解决前面例子中的问题,我们可以手动为ht_opt$HEATMAP_LEGEND_PADDING
和ht_opt$TITLE_PADDING
设置一个合适的值。
ht_opt$HEATMAP_LEGEND_PADDING = unit(5, "mm")
ht_opt$TITLE_PADDING = unit(c(9, 2), "mm") # bottom and top padding
Heatmap3D(mat, name = "mat", column_title = "This is a 3D heatmap")
通过ht_opt(RESET = TRUE)
以下方式重置全局选项:
ht_opt(RESET = TRUE)
接下来,我将演示另一个应用于众所周知的麻疹疫苗数据集的示例。首先,我展示了“普通 2D 热图”。可以在此处找到用于生成热图的代码。
要将其更改为 3D 可视化,只需替换Heatmap()
为 Heatmap3D()
并且大多数原始参数Heatmap()
仍然可以放在那里。为简单起见,在 3D 热图中,我删除了顶部注释和右侧注释。
mat = readRDS(system.file("extdata", "measles.rds", package = "ComplexHeatmap"))
year_text = as.numeric(colnames(mat))
year_text[year_text %% 10 != 0] = ""
ha_column = HeatmapAnnotation(
year = anno_text(year_text, rot = 0, location = unit(1, "npc"), just = "top")
)
col_fun = circlize::colorRamp2(c(0, 800, 1000, 127000), c("white", "cornflowerblue", "yellow", "red"))
ht_opt$TITLE_PADDING = unit(c(15, 2), "mm")
Heatmap3D(mat, name = "cases", col = col_fun,
cluster_columns = FALSE, show_row_dend = FALSE,
show_column_names = FALSE,
row_names_side = "left", row_names_gp = gpar(fontsize = 8),
column_title = 'Measles cases in US states 1930-2001\nVaccine introduced 1961',
bottom_annotation = ha_column,
heatmap_legend_param = list(at = c(0, 5e4, 1e5, 1.5e5),
labels = c("0", "50k", "100k", "150k")),
# new arguments for Heatmap3D()
bar_rel_width = 1, bar_rel_height = 1, bar_max_length = unit(2, "cm")
)
顺便说一下,还可以通过包InteractiveComplexHeatmap将静态 3D 热图转换为交互式 Shiny 应用程序。见下图:
Heatmap3D()
可以做很多与Heatmap()
相同的事情,例如添加注释、拆分热图或通过+
/%v%
连接更多热图。但由于 3D 可视化通常不是一个好主意,而且它实际上不会为您提供比 2D 可视化更多的信息,因此,如果您想使用Heatmap3D()
,您最好保持它尽可能简单。另外,请将其应用于小矩阵,大矩阵需要很长时间才能生成。
基因组级热图
参考链接
许多人对制作具有多个轨迹的基因组规模热图比较感兴趣,例如此处 和 此处的示例。在本章中,我将演示如何使用ComplexHeatmap实现它 。
为了制作基因组规模图,我们首先需要染色体水平的范围。有很多方法可以获取这些信息。在下面,我使用 circlize::read.chromInfo()
函数。
library(circlize)
library(GenomicRanges)
chr_df = read.chromInfo()$df
chr_df = chr_df[chr_df$chr %in% paste0("chr", 1:22), ]
chr_gr = GRanges(seqnames = chr_df[, 1], ranges = IRanges(chr_df[, 2] + 1, chr_df[, 3]))
chr_gr
## GRanges object with 22 ranges and 0 metadata columns:
## seqnames ranges strand
##
## [1] chr1 1-249250621 *
## [2] chr2 1-243199373 *
## [3] chr3 1-198022430 *
## [4] chr4 1-191154276 *
## [5] chr5 1-180915260 *
## ... ... ... ...
## [18] chr18 1-78077248 *
## [19] chr19 1-59128983 *
## [20] chr20 1-63025520 *
## [21] chr21 1-48129895 *
## [22] chr22 1-51304566 *
## -------
## seqinfo: 22 sequences from an unspecified genome; no seqlengths
在最终的热图中,每一行(如果基因组方向是垂直的)或每一列(如果基因组方向是水平的)实际上代表一个基因组窗口,因此我们需要用等宽窗口分割基因组。这里我使用 EnrichedHeatmap::makeWindows()
函数将基因组分割为 1MB 窗口(这里的两个元列chr_window
可以忽略)。
library(EnrichedHeatmap)
chr_window = makeWindows(chr_gr, w = 1e6)
chr_window
## GRanges object with 2875 ranges and 2 metadata columns:
## seqnames ranges strand | .i_query .i_window
## |
## [1] chr1 1-1000000 * | 1 1
## [2] chr1 1000001-2000000 * | 1 2
## [3] chr1 2000001-3000000 * | 1 3
## [4] chr1 3000001-4000000 * | 1 4
## [5] chr1 4000001-5000000 * | 1 5
## ... ... ... ... . ... ...
## [2871] chr22 46000001-47000000 * | 22 47
## [2872] chr22 47000001-48000000 * | 22 48
## [2873] chr22 48000001-49000000 * | 22 49
## [2874] chr22 49000001-50000000 * | 22 50
## [2875] chr22 50000001-51000000 * | 22 51
## -------
## seqinfo: 22 sequences from an unspecified genome; no seqlengths
为了将基因组尺度信号可视化为热图以及其他轨迹,现在的任务是通过重叠基因组窗口和基因组信号来计算 1MB 窗口中的平均信号。这里我实现了一个功能 average_in_window()
。这个函数改编自HilbertCurve 包,因为那里有类似的任务。
average_in_window = function(window, gr, v, method = "weighted", empty_v = NA) {
if(missing(v)) v = rep(1, length(gr))
if(is.null(v)) v = rep(1, length(gr))
if(is.atomic(v) && is.vector(v)) v = cbind(v)
v = as.matrix(v)
if(is.character(v) && ncol(v) > 1) {
stop("`v` can only be a character vector.")
}
if(length(empty_v) == 1) {
empty_v = rep(empty_v, ncol(v))
}
u = matrix(rep(empty_v, each = length(window)), nrow = length(window), ncol = ncol(v))
mtch = as.matrix(findOverlaps(window, gr))
intersect = pintersect(window[mtch[,1]], gr[mtch[,2]])
w = width(intersect)
v = v[mtch[,2], , drop = FALSE]
n = nrow(v)
ind_list = split(seq_len(n), mtch[, 1])
window_index = as.numeric(names(ind_list))
window_w = width(window)
if(is.character(v)) {
for(i in seq_along(ind_list)) {
ind = ind_list[[i]]
if(is.function(method)) {
u[window_index[i], ] = method(v[ind], w[ind], window_w[i])
} else {
tb = tapply(w[ind], v[ind], sum)
u[window_index[i], ] = names(tb[which.max(tb)])
}
}
} else {
if(method == "w0") {
gr2 = reduce(gr, min.gapwidth = 0)
mtch2 = as.matrix(findOverlaps(window, gr2))
intersect2 = pintersect(window[mtch2[, 1]], gr2[mtch2[, 2]])
width_intersect = tapply(width(intersect2), mtch2[, 1], sum)
ind = unique(mtch2[, 1])
width_setdiff = width(window[ind]) - width_intersect
w2 = width(window[ind])
for(i in seq_along(ind_list)) {
ind = ind_list[[i]]
x = colSums(v[ind, , drop = FALSE]*w[ind])/sum(w[ind])
u[window_index[i], ] = (x*width_intersect[i] + empty_v*width_setdiff[i])/w2[i]
}
} else if(method == "absolute") {
for(i in seq_along(ind_list)) {
u[window_index[i], ] = colMeans(v[ind_list[[i]], , drop = FALSE])
}
} else if(method == "weighted") {
for(i in seq_along(ind_list)) {
ind = ind_list[[i]]
u[window_index[i], ] = colSums(v[ind, , drop = FALSE]*w[ind])/sum(w[ind])
}
} else {
if(is.function(method)) {
for(i in seq_along(ind_list)) {
ind = ind_list[[i]]
u[window_index[i], ] = method(v[ind], w[ind], window_w[i])
}
} else {
stop("wrong method.")
}
}
}
return(u)
}
在average_in_window()
函数中,有以下参数:
-
window
:GRanges
基因组窗口的对象。 -
gr
:GRanges
基因组信号的对象。 -
v
: 向量或矩阵。这是与gr
关联的值,它的长度应与gr
或nrow
相同。v
可以是数字或字符。如果是missing
或NULL
,则将 值 1 分配给gr
中的每个区域。如果v
是数字,则可以是向量或矩阵,如果v
是字符,则只能是向量。 -
method
:总结每个基因组窗口信号的方法。 -
empty_v
: 如果没有区域gr
与其重叠,则为窗口的默认值。
该函数返回一个与window
具有相同行长和顺序的矩阵。
重叠模型如下图所示。底部的红线代表某个基因组窗口。顶部的黑线是与窗口重叠的基因组信号区域。粗线表示信号区域和窗口之间的相交部分。
对于一个给定的窗口,n是与窗口重叠的信号区域的数量(上图中为5),wi是相交段的宽度(黑色粗线),xi是与原始区域相关联的信号值。
使用函数average_in_window()
,我可以将基因组信号转换为基于窗口的矩阵。在以下示例中,我生成了大约 1000 个随机基因组区域,其中包含 10 列随机值(以模拟 10 个样本)。
bed1 = generateRandomBed(nr = 1000, nc = 10) # generateRandomBed() is from circlize package
# convert to a GRanes object
gr1 = GRanges(seqnames = bed1[, 1], ranges = IRanges(bed1[, 2], bed1[, 3]))
num_mat = average_in_window(chr_window, gr1, bed1[, -(1:3)])
dim(num_mat)
## [1] 2875 10
head(num_mat)
## [,1] [,2] [,3] [,4] [,5] [,6]
## [1,] 0.17092940 -0.4323175 0.5814975 0.5419019 -1.3986643 -0.73240405
## [2,] 0.17092940 -0.4323175 0.5814975 0.5419019 -1.3986643 -0.73240405
## [3,] 0.17092940 -0.4323175 0.5814975 0.5419019 -1.3986643 -0.73240405
## [4,] 0.17092940 -0.4323175 0.5814975 0.5419019 -1.3986643 -0.73240405
## [5,] 0.17092940 -0.4323175 0.5814975 0.5419019 -1.3986643 -0.73240405
## [6,] 0.06902516 -0.6065132 0.5130708 -0.0876663 0.4215547 -0.08663985
## [,7] [,8] [,9] [,10]
## [1,] 0.8572341 0.04271758 -0.6805558 1.1822941
## [2,] 0.8572341 0.04271758 -0.6805558 1.1822941
## [3,] 0.8572341 0.04271758 -0.6805558 1.1822941
## [4,] 0.8572341 0.04271758 -0.6805558 1.1822941
## [5,] 0.8572341 0.04271758 -0.6805558 1.1822941
## [6,] -1.0614186 -0.10839748 0.3643813 -0.2047742
前五个基因组窗口没有关联的值,因为没有gr1
与它们重叠的区域 ,因此,empty_v
默认情况下它们取自的值NA
。
要可视化的第二个数据是具有特征信号的 10 个基因组区域列表(假设它们是来自 10 个样本的拷贝数变异结果)。在每个随机区域,我还从它们中抽取了 20 个样本,只是为了使它们在基因组中变得稀疏。
bed_list = lapply(1:10, function(i) {
generateRandomBed(nr = 1000, nc = 1,
fun = function(n) sample(c("gain", "loss"), n, replace = TRUE))
})
char_mat = NULL
for(i in 1:10) {
bed = bed_list[[i]]
bed = bed[sample(nrow(bed), 20), , drop = FALSE]
gr_cnv = GRanges(seqnames = bed[, 1], ranges = IRanges(bed[, 2], bed[, 3]))
char_mat = cbind(char_mat, average_in_window(chr_window, gr_cnv, bed[, 4]))
}
要可视化的第三个数据只是具有两个数字列的基因组区域,其中两列将可视化为点轨迹,第一列将可视化为条形图轨迹。
bed2 = generateRandomBed(nr = 100, nc = 2)
gr2 = GRanges(seqnames = bed2[, 1], ranges = IRanges(bed2[, 2], bed2[, 3]))
v = average_in_window(chr_window, gr2, bed2[, 4:5])
要可视化的第四个数据是我们要在图中标记的基因符号列表。gr3
包含基因的基因组位置及其符号。该变量at
包含相应窗口的行索引chr_window
和labels
包含基因名称。如以下代码所示,我只是findOverlaps()
将基因区域与基因组窗口关联起来。
bed3 = generateRandomBed(nr = 40, nc = 0)
gr3 = GRanges(seqnames = bed3[, 1], ranges = IRanges(bed3[, 2], bed3[, 2]))
gr3$gene = paste0("gene_", 1:length(gr3))
mtch = as.matrix(findOverlaps(chr_window, gr3))
at = mtch[, 1]
labels = mcols(gr3)[mtch[, 2], 1]
现在拥有了所有变量并准备好制作热图。在此之前,为了更好地控制热图,我设置chr
了一个因子来控制最终图中染色体的顺序,并创建一个变量subgroup
来模拟矩阵中两个子组的 10 列。
chr = as.vector(seqnames(chr_window))
chr_level = paste0("chr", 1:22)
chr = factor(chr, levels = chr_level)
subgroup = rep(c("A", "B"), each = 5)
以下代码使热图带有附加轨道。该图是两个热图和三行注释的组合。不要被大量的争论吓到。
library(ComplexHeatmap)
ht_opt$TITLE_PADDING = unit(c(4, 4), "points")
ht_list = Heatmap(num_mat, name = "mat", col = colorRamp2(c(-1, 0, 1), c("green", "white", "red")),
row_split = chr, cluster_rows = FALSE, show_column_dend = FALSE,
column_split = subgroup, cluster_column_slices = FALSE,
column_title = "numeric matrix",
top_annotation = HeatmapAnnotation(subgroup = subgroup, annotation_name_side = "left"),
row_title_rot = 0, row_title_gp = gpar(fontsize = 10), border = TRUE,
row_gap = unit(0, "points")) +
Heatmap(char_mat, name = "CNV", col = c("gain" = "red", "loss" = "blue"),
border = TRUE, column_title = "character matrix") +
rowAnnotation(label = anno_mark(at = at, labels = labels)) +
rowAnnotation(pt = anno_points(v, gp = gpar(col = 4:5), pch = c(1, 16)),
width = unit(2, "cm")) +
rowAnnotation(bar = anno_barplot(v[, 1], gp = gpar(col = ifelse(v[ ,1] > 0, 2, 3))),
width = unit(2, "cm"))
draw(ht_list, merge_legend = TRUE)
很容易使热图的垂直排列(用于%v%
连接热图!)。只需仔细切换行相关参数和列相关参数即可。
注意使用了一个技巧来排列染色体名称。由于小染色体的染色体名称会重叠,因此只需在相邻染色体名称之前或之后添加\n
。
ht_list = Heatmap(t(num_mat), name = "mat", col = colorRamp2(c(-1, 0, 1), c("green", "white", "red")),
column_split = chr, cluster_columns = FALSE, show_row_dend = FALSE,
row_split = subgroup, cluster_row_slices = FALSE,
row_title = "numeric matrix",
left_annotation = rowAnnotation(subgroup = subgroup, show_annotation_name = FALSE,
annotation_legend_param = list(
subgroup = list(direction = "horizontal", title_position = "lefttop", nrow = 1))),
column_title_gp = gpar(fontsize = 10), border = TRUE,
column_gap = unit(0, "points"),
column_title = ifelse(1:22 %% 2 == 0, paste0("\n", chr_level), paste0(chr_level, "\n")),
heatmap_legend_param = list(direction = "horizontal", title_position = "lefttop")) %v%
Heatmap(t(char_mat), name = "CNV", col = c("gain" = "red", "loss" = "blue"),
border = TRUE, row_title = "character matrix",
heatmap_legend_param = list(direction = "horizontal", title_position = "lefttop", nrow = 1)) %v%
HeatmapAnnotation(label = anno_mark(at = at, labels = labels, side = "bottom")) %v%
HeatmapAnnotation(pt = anno_points(v, gp = gpar(col = 4:5), pch = c(1, 16)),
annotation_name_side = "left", height = unit(2, "cm")) %v%
HeatmapAnnotation(bar = anno_barplot(v[, 1], gp = gpar(col = ifelse(v[ ,1] > 0, 2, 3))),
annotation_name_side = "left", height = unit(2, "cm"))
draw(ht_list, heatmap_legend_side = "bottom", merge_legend = TRUE)