欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

如何轻松用R语言ggplot2制作环状热力图:一个小案例教程

最编程 2024-02-10 13:06:19
...

点击上方关注我们






回顾一下需要搞定的图:

万恶之源:

昨天我们基本上可以做出这张图的大部分了,剩下的是 内圈的红色注释 ,今天尝试一下。

1、构造数据





我们在 R 里手动构造 200 个基因表达矩阵,锻炼一下你的 R 功底:

# 加载R包
library(tidyverse)
library(reshape2)
library(ggnewscale)

# 随机生成5个字母连接的基因名
sample(LETTERS[1:26],5,replace = T) %>% paste(.,sep = '',collapse = '')

[1"XANLV"

# 写个批量随机生成名字的函数
add_name <- function(n){
  sample(LETTERS[1:26],5,replace = T) %>% paste(.,sep = '',collapse = '')
}

# 生成200个名字
my_name <- lapply(1:200, add_name) %>% Reduce('rbind',.)

# 生成200行随机矩阵
mat <- matrix(rnorm(800),ncol = 4)

# 转为数据框
mat <- as.data.frame(mat)

# 增加行名
mat$gene_name <- my_name

# 增加列名
colnames(mat)[1:4] <- paste('S',1:4,sep = '')

# 把行名换成数字
rownames(mat) <- 1:200

# 查看内容
head(mat,3)

         S1         S2         S3           S4 gene_name
1 -1.610566  0.2707304  2.4928545  0.004407928     MRSXW
2 -1.554155  0.8668774 -0.3788507 -1.169215463     CXFVI
3  1.441376 -1.0082396 -0.5090956  0.717615026     SOMUN

# 宽数据转长数据
cirp <- melt(mat)

# 查看内容
head(cirp,3)

  gene_name variable     value
1     MRSXW       S1 -1.610566
2     CXFVI       S1 -1.554155
3     SOMUN       S1  1.441376

2、简单环形热图





到这里我们得到了 4 给样本,200 个基因的表达矩阵,然后我们按昨天先绘制一个环形热图开口。

计算角度:

# 取一个样本用作标签
res <- cirp %>% filter(variable == 'S1')

# 添加文字标签

# 计算角度
res$ang <- seq(from = (360/nrow(res)) / 1.5,
               to = (1.5* (360/nrow(res))) - 360,
               length.out = nrow(res)) + 80

# 根据角度确定朝向的方向
res$hjust <- 0
res$hjust[which(res$ang < -90)] <- 1
res$ang[which(res$ang < -90)] <- (180+res$ang)[which(res$ang < -90)]

绘图:

# 添加Y轴数值
cirp$var <- rep(1:200,4)

# 绘制开口热图
ggplot(cirp,aes(x = var,y = variable)) +
  geom_tile(aes(fill = value),color = 'white') +
  scale_fill_gradient2(midpoint = 0,
                       low = '#3C8DAD',
                       mid = "white",
                       high = '#FF6767') +
  scale_y_discrete(expand = expansion(mult = c(2,0))) +
  scale_x_discrete(expand = expansion(mult = c(0,0.05))) +
  coord_polar(theta = 'x') +
  theme_void() +
  geom_text(data = res,
            aes(x = as.numeric(rownames(res)),
                y = 4.6,
                label = gene_name, angle = ang, hjust = hjust),
            size = 2)

3、添加基因注释





接下来给基因添加注释来区别哪些基因是哪一类或者突出某一类感兴趣靶标基因

# 添加基因注释
g_anno <- data.frame(value = c(rep('none',15),rep('target',35),rep('none',10),
                               rep('target',15),rep('none',20),rep('target',5),
                               rep('none',50),rep('target',50)))

# 查看
table(g_anno)

g_anno
  none target
    95    105

先把注释图画出来看看:

# 注释条形图
ggplot() +
  # 添加基因注释
  geom_bar(data = g_anno,stat = 'identity',
           aes(x = 1:200,y = 0.25,fill = value),
           width = 1,
           color = NA) +
  scale_fill_manual(name = 'gene annotation',values = c('none' = 'white','target' = '#E8E46E'))

没啥问题再把四个热图加上看看:

# 添加热图
p <- ggplot() +
  # 添加基因注释
  geom_bar(data = g_anno,stat = 'identity',
           aes(x = 1:200,y = 0.25,fill = value),
           width = 1,
           color = NA) +
  scale_fill_manual(name = 'gene annotation',values = c('none' = 'white','target' = '#E8E46E')) +
  # 添加第一个环s1
  # 新增图例
  new_scale("fill") +
  geom_tile(data = cirp[which(cirp$variable == 'S1'),],
            aes(x = 1:200,y = 1,fill = value),
            color = 'white') +
  scale_fill_gradient2(midpoint = 0,
                       low = 'green',
                       mid = "black",
                       high = 'red',
                       name = 'ONE') +
  # 添加第一个环s2
  geom_tile(data = cirp[which(cirp$variable == 'S2'),],
            aes(x = 1:200,y = 2,fill = value),
            color = 'white') +
  # 添加第一个环s3
  geom_tile(data = cirp[which(cirp$variable == 'S3'),],
            aes(x = 1:200,y = 3,fill = value),
            color = 'white') +
  # 添加第一个环s4
  geom_tile(data = cirp[which(cirp$variable == 'S4'),],
            aes(x = 1:200,y = 4,fill = value),
            color = 'white') +
  ylim(-3,5)
p

看起来没问题,在这里我们要注意以下注释的 y = 0.25 这个参数,用来调整 注释条与热图的相对位置

其次 ylim 参数,越负,环形热图中间就越空,接下来掰弯它,加个基因名:

# 掰弯,添加基因名
library(circlize)

p + coord_polar(theta = 'x') +
  theme_void() +
  geom_text(data = res,
            aes(x = as.numeric(rownames(res)),
                y = 4.6,
                label = gene_name, angle = ang, hjust = hjust),
            # 给基因名添加颜色
            color = rand_color(200),
            size = 2)

4、添加多层注释





有时候可能需要对基因添加多个注释,无非是再加一层条形图而已,调换位置就好:

# 添加多层注释

# 添加基因注释
g_anno1 <- data.frame(type = c(rep('important',100),rep('significance',100)))
g_anno2 <- data.frame(value = c(rep('none',15),rep('target',35),rep('none',10),
                               rep('target',15),rep('none',20),rep('target',5),
                               rep('none',50),rep('target',50)))

# 注释条形图
p1 <- ggplot() +
  # 添加基因注释1
  geom_bar(data = g_anno1,stat = 'identity',
           aes(x = 1:200,y = 0.25,fill = type),
           width = 1,
           color = NA) +
  # 添加基因注释2
  geom_bar(data = g_anno2,stat = 'identity',
           aes(x = 1:200,y = -0.25,fill = value),
           width = 1,
           color = NA) +
  scale_fill_manual(name = 'gene annotation',
                    values = c('none' = 'white','target' = '#E8E46E',
                               'important' = '#81B214','significance' = '#E40017'))
p1

添加热图检查位置是否正确:

# 添加热图
p3 <- p1 + # 添加第一个环s1
  # 新增图例
  new_scale("fill") +
  geom_tile(data = cirp[which(cirp$variable == 'S1'),],
            aes(x = 1:200,y = 1,fill = value),
            color = 'white') +
  scale_fill_gradient2(midpoint = 0,
                       low = 'green',
                       mid = "black",
                       high = 'red',
                       name = 'ONE') +
  # 添加第一个环s2
  geom_tile(data = cirp[which(cirp$variable == 'S2'),],
            aes(x = 1:200,y = 2,fill = value),
            color = 'white') +
  # 添加第一个环s3
  geom_tile(data = cirp[which(cirp$variable == 'S3'),],
            aes(x = 1:200,y = 3,fill = value),
            color = 'white') +
  # 添加第一个环s4
  geom_tile(data = cirp[which(cirp$variable == 'S4'),],
            aes(x = 1:200,y = 4,fill = value),
            color = 'white') +
  ylim(-3,5)
p3

掰弯整起:

# 掰弯,开口型
p3 + coord_polar(theta = 'x') +
  theme_void() + xlim(0,205) +
  geom_text(data = res,
            aes(x = as.numeric(rownames(res)),
                y = 4.6,
                label = gene_name, angle = ang, hjust = hjust),
            # 给基因名添加颜色
            color = rand_color(200),
            size = 2)

完美。

5、样本注释





有时候还需要对样本进行注释,同样的,添加条形图就完事:

# 注释条形图
p1 <- ggplot() +
  # 添加基因注释1
  geom_bar(data = g_anno2,stat = 'identity',
           aes(x = 1:200,y = -0.5,fill = value),
           width = 1,
           color = NA) +
  # 添加基因注释2
  geom_bar(data = g_anno1,stat = 'identity',
           aes(x = 1:200,y = -0.25,fill = type),
           width = 1,
           color = NA) +
  scale_fill_manual(name = 'gene annotation',
                    values = c('none' = 'white','target' = '#E8E46E',
                               'important' = '#81B214','significance' = '#E40017')) +
  # 新增图例
  new_scale("fill") +
  geom_bar(data = s_anno,stat = 'identity',
           aes(x = -2,y = 1,fill = samp),
           width = 5,
           color = NA) +
  scale_fill_manual(name = 'sample annotation',
                    values = c('control' = '#FA26A0','treat' = '#24A19C'))
p1

这里需要注意的点还是图层 Y 轴的位置调整

添加热图检查位置是否正确,这里 y 的位置也要稍作修整一下:

# 添加热图
p3 <- p1 +
  # 添加第一个环s1
  # 新增图例
  new_scale("fill") +
  geom_tile(data = cirp[which(cirp$variable == 'S1'),],
            aes(x = 1:200,y = 0.5,fill = value),
            color = 'white') +
  scale_fill_gradient2(midpoint = 0,
                       low = 'green',
                       mid = "black",
                       high = 'red',
                       name = 'ONE') +
  # 添加第一个环s2
  geom_tile(data = cirp[which(cirp$variable == 'S2'),],
            aes(x = 1:200,y = 1.5,fill = value),
            color = 'white') +
  # 添加第一个环s3
  geom_tile(data = cirp[which(cirp$variable == 'S3'),],
            aes(x = 1:200,y = 2.5,fill = value),
            color = 'white') +
  # 添加第一个环s4
  geom_tile(data = cirp[which(cirp$variable == 'S4'),],
            aes(x = 1:200,y = 3.5,fill = value),
            color = 'white') +
  ylim(-3,5)
p3

掰弯整起:

# 掰弯,开口型
p3 + coord_polar(theta = 'x') +
  theme_void() + xlim(-5,205) +
  geom_text(data = res,
            aes(x = as.numeric(rownames(res)),
                y = 4.3,
                label = gene_name, angle = ang, hjust = hjust),
            # 给基因名添加颜色
            color = rand_color(200),
            size = 2)

调整一下参数,优化一下: