自己如何画气泡图dotplot?

今天是生信星球陪你的第803天


大神一句话,菜鸟跑半年。我不是大神,但我可以缩短你走弯路的半年~

就像歌儿唱的那样,如果你不知道该往哪儿走,就留在这学点生信好不好~

这里有豆豆和花花的学习历程,从新手到进阶,生信路上有你有我!

豆豆写于2021.4.14
看到David McGaughey写了一篇博客:http://davemcg.github.io/post/lets-plot-scrna-dotplots/,他介绍了一些关于dotplot的事情。拿来学习一下

看完这篇,从出图到美观

首先,什么是气泡图dotplot?

比如 来自文章
https://www.sciencedirect.com/science/article/pii/S0092867419300376的这个G图就是dotplot

它和heatmap类似,要么行是基因,列是样本;要么行是样本,列是基因,并且还支持聚类。主要用于体现不同组之间的基因差异。

可以认为dotplot是heatmap的升级版,heatmap可以认为每一个样本的每一个基因,在图上是方块,可以用颜色来表示表达量高低;但是dotplot除了可以用颜色表示表达量高低以外,还能通过点(或者说“气泡”)的大小,来表示某个样本中的细胞数量/比例。例如:如果说某个样本中有更多的细胞表达了这个基因,那么这个位置就会形状更大,颜色更深。

上面说到,它可以反映某个样本中的细胞数量多少,因此在单细胞数据分析中经常出现。

例如在Seurat中:https://satijalab.org/seurat/archive/v3.0/visualization_vignette.html

开始DIY

准备数据

library(tidyverse)
library(ggdendro)
library(cowplot)
library(ggtree)
library(patchwork)

gene_cluster <- read_tsv('https://github.com/davemcg/davemcg.github.io/raw/master/content/post/scRNA_dotplot_data.tsv.gz')

gene_cluster %>% sample_n(5)
## # A tibble: 5 x 6
##   Gene    cluster cell_ct cell_exp_ct    count Group     
##   <chr>   <chr>     <dbl>       <dbl>    <dbl> <chr>     
## 1 MYH11   c22         278           9 0.0324   Fibroblast
## 2 CARM1   c19         922           8 0.00868  Astrocyte 
## 3 MICA    c11        1870          22 0.0118   Astrocyte 
## 4 SLC39A3 c02        3320           3 0.000904 Fibroblast
## 5 DVL3    c20         336         254 1.30     Neuron

  • cluster是scRNA中的cluster

  • cell_ct 是cluster中的细胞数量

  • cell_exp_ct 是该cluster中检测到该基因的细胞数量

  • count是基因的mean log2表达量

  • Group是cluster属于的细胞类型

最简单的作图

把cluster中存在基因表达的细胞数量百分比做出来,就可以展示为气泡的大小

gene_cluster %>% filter(Gene %in% markers) %>%     mutate(`% Expressing` = (cell_exp_ct/cell_ct) * 100) %>%     ggplot(aes(x=cluster, y = Gene, color = count, size = `% Expressing`)) +     geom_point() 

看到很多气泡为0,那么就把等于0或者接近0的气泡删掉

gene_cluster %>% filter(Gene %in% markers) %>% 
    mutate(`% Expressing` = (cell_exp_ct/cell_ct) * 100) %>% 
    filter(count > 0, `% Expressing` > 1) %>% 
    ggplot(aes(x=cluster, y = Gene, color = count, size = `% Expressing`)) + 
    geom_point() 

修改颜色、主题、坐标轴

gene_cluster %>% filter(Gene %in% markers) %>%   mutate(`% Expressing` = (cell_exp_ct/cell_ct) * 100) %>%   filter(count > 0, `% Expressing` > 1) %>%   ggplot(aes(x=cluster, y = Gene, color = count, size = `% Expressing`)) +   geom_point() +   scale_color_viridis_c(name = 'log2 (count + 1)') +   cowplot::theme_cowplot() +   theme(axis.line  = element_blank()) +  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +  ylab('') +  theme(axis.ticks = element_blank()) 

看到存在某个基因表达量很高,影响了其他基因的展示
例如中间颜色最黄的那个(KCNQ1),那索性就把它作为颜色的最大值好了(比如这里的4)

设置图例颜色的范围

使用scale_color_gradientn设置渐变色的范围为0-4,如果有的点超过了4,那么通过oob = scales::squish将它硬生生压到4

dotplot <- gene_cluster %>% filter(Gene %in% markers) %>% 
  mutate(`% Expressing` = (cell_exp_ct/cell_ct) * 100) %>% 
  filter(count > 0, `% Expressing` > 1) %>% 
  ggplot(aes(x=cluster, y = Gene, color = count, size = `% Expressing`)) + 
  geom_point() + 
  cowplot::theme_cowplot() + 
  theme(axis.line  = element_blank()) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
  ylab('') +
  theme(axis.ticks = element_blank()) +
  scale_color_gradientn(colours = viridis::viridis(20), limits = c(0,4), oob = scales::squish, name = 'log2 (count + 1)')

dotplot

看上去,比最初好看了许多。这时我们已经调整完了表达量、数量,不过还有聚类可以再加上去

ggplot没有内置聚类树,但可以有以下几个选择:

  • 直接用hclust对基因进行聚类:mutate(Gene = factor(Gene, levels = YOURNEWGENEORDER) ,然后做的图中基因的排序就会是聚类之后的顺序,但是图中不会出现聚类树

  • 使用ComplexHeatmap,但过程有些复杂

  • 使用`ggtree `:我们下面就看看这个方法

先用ggtree 单独画一个聚类树

# devtools::install_github('YuLab-SMU/ggtree')# 首先将数据变成数据框,行为基因,列为样本mat <- gene_cluster %>%     filter(Gene %in% markers) %>%     select(-cell_ct, -cell_exp_ct, -Group) %>%  # drop unused columns to faciliate widening    pivot_wider(names_from = cluster, values_from = count) %>%     data.frame() # make df as tibbles -> matrix annoyingrow.names(mat) <- mat$Gene  mat <- mat[,-1] 

> mat[1:4,1:4]              c00         c01         c02         c03MICA   0.28905878 0.023216308 0.035417157 0.032588291ESRRA  0.04856985 0.015737532 0.020356916 0.008599147CARM1  0.08822628 0.011939390 0.002409639 0.006500512IGFBP7 4.26602825 0.001864372 0.002409639 0.081627805

# 然后转为矩阵后用dist默认方法(欧氏距离),再进行hclustclust <- hclust(dist(mat %>% as.matrix()))

ddgram <- as.dendrogram(clust) # create dendrogram (如果这里报错,可能是R版本太低,用4.0以上是正常的)ggtree_plot <- ggtree::ggtree(ddgram)ggtree_plot

然后把聚类树和之前的图用cowplot粘起来

plot_grid(ggtree_plot, dotplot, nrow = 1, rel_widths = c(0.5,2), align = 'h')

出现一个问题:我们这里的聚类树,是真实的基因聚类吗?
看到这里的基因排序并没有改变,只是被我们硬生生和聚类树粘在了一起

如何调整基因的顺序

# 拿到聚类后的基因顺序,然后变成因子> clust$labels[clust$order] [1] 'KCNQ1'   'IGFBP7'  'LRRC29'  'MSH2'    'TOM1L2'  'FAM228B' 'MYH11'   'ISY1'    'ROCK1'   'OR5P2'   'JRK'    [12] 'STAT2'   'GPR63'   'WDR48'   'CACNG7'  'SLC39A3' 'SPRED2'  'RHBDD3'  'LYNX1'   'CELA1'   'PAK2'    'FAM129B'[23] 'S100A12' 'CCNI'    'UCN'     'NDUFA1'  'ESRRA'   'CARM1'   'CDH22'   'SLC10A7' 'FTSJ3'   'ZFP91'   'MICA'   [34] 'TRHR'    'VGLL3'   'TBL2'    'DVL3'   

dotplot <- gene_cluster %>% filter(Gene %in% markers) %>%   mutate(`% Expressing` = (cell_exp_ct/cell_ct) * 100,         Gene = factor(Gene, levels = clust$labels[clust$order])) %>%   #filter(count > 0, `% Expressing` > 1) %>%   ggplot(aes(x=cluster, y = Gene, color = count, size = `% Expressing`)) +   geom_point() +   cowplot::theme_cowplot() +   theme(axis.line  = element_blank()) +  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +  ylab('') +  theme(axis.ticks = element_blank()) +  scale_color_gradientn(colours = viridis::viridis(20), limits = c(0,4), oob = scales::squish, name = 'log2 (count + 1)')

dotplot

这才是真实的聚类以后的结果,才能继续和聚类树粘在一起

如何将聚类树和气泡图之间的空白区域减少?

可以把基因ID移到右侧:scale_y_discrete(position = 'right')

dotplot <- gene_cluster %>% filter(Gene %in% markers) %>% 
  mutate(`% Expressing` = (cell_exp_ct/cell_ct) * 100,
         Gene = factor(Gene, levels = clust$labels[clust$order])) %>% 
  filter(count > 0, `% Expressing` > 1) %>% 
  ggplot(aes(x=cluster, y = Gene, color = count, size = `% Expressing`)) + 
  geom_point() + 
  cowplot::theme_cowplot() + 
  theme(axis.line  = element_blank()) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
  ylab('') +
  theme(axis.ticks = element_blank()) +
  scale_color_gradientn(colours = viridis::viridis(20), limits = c(0,4), oob = scales::squish, name = 'log2 (count + 1)') +
  scale_y_discrete(position = 'right')
#################################################

plot_grid(ggtree_plot, NULL, dotplot, nrow = 1, rel_widths = c(0.5,-0.05, 2), align = 'h')

然后我们继续对列(样本)进行聚类

和之前hclust代码类似,只是这里在hclust的时候,需要转置一下

mat <- gene_cluster %>%     filter(Gene %in% markers) %>%     select(-cell_ct, -cell_exp_ct, -Group) %>%     pivot_wider(names_from = cluster, values_from = count) %>%     data.frame() row.names(mat) <- mat$Gene  mat <- mat[,-1] 

v_clust <- hclust(dist(mat %>% as.matrix() %>% t()))  #加一个转置,对列进行计算

ddgram_col <- as.dendrogram(v_clust)ggtree_plot_col <- ggtree(ddgram_col) + layout_dendrogram()ggtree_plot_col

然后,就是把各个部分粘在一起

一个重点就是:如何将每个部分对齐?

使用aplot::xlim2 以及 aplot::ylim2 ,将主图(气泡图)分别与样本的聚类树、基因的聚类树对齐

xlim2 : set axis limits of a 'ggplot' object based on the x limits of another 'ggplot' object

需要注意,现在xlim2ylim2已经不在ggtree中了,迁移到了aplot

remotes::install_github('YuLab-SMU/aplot')

代码实现:

ggtree_plot_col <- ggtree_plot_col + xlim2(dotplot)ggtree_plot <- ggtree_plot + ylim2(dotplot)

样本的注释信息可以加进来

这里的数据中:各个cluster属于哪个细胞类型,就是样本的注释信息

同样使用xlim2保证和主图的x轴(即样本)对齐

labels <- ggplot(gene_cluster %>% 
                     mutate(`Cell Type` = Group,
                            cluster = factor(cluster, levels = v_clust$labels[v_clust$order])), 
                 aes(x = cluster, y = 1, fill = `Cell Type`)) + 
    geom_tile() + 
    scale_fill_brewer(palette = 'Set1') + 
    theme_nothing() +
    xlim2(dotplot)

# 一直保留在底部
legend <- plot_grid(get_legend(labels + theme(legend.position='bottom')))

最后,就是全部画在一起

这个过程,估计要反复修改

首先看到是这样的:除了底部的legend,一共有3列,5行

plot_spacer() + plot_spacer() + ggtree_plot_col +    plot_spacer() + plot_spacer() + labels +     plot_spacer() + plot_spacer() + plot_spacer() +    ggtree_plot + plot_spacer() + dotplot +     plot_spacer() + plot_spacer() + legend +     plot_layout(ncol = 3)

然后就是要调整3列的宽度

plot_spacer() + plot_spacer() + ggtree_plot_col +
    plot_spacer() + plot_spacer() + labels + 
    plot_spacer() + plot_spacer() + plot_spacer() +
    ggtree_plot + plot_spacer() + dotplot + 
    plot_spacer() + plot_spacer() + legend + 
    plot_layout(ncol = 3,widths = c(0.7, -0.1, 4))

再调整每一行的高度

plot_spacer() + plot_spacer() + ggtree_plot_col +    plot_spacer() + plot_spacer() + labels +     plot_spacer() + plot_spacer() + plot_spacer() +    ggtree_plot + plot_spacer() + dotplot +     plot_spacer() + plot_spacer() + legend +     plot_layout(ncol = 3,widths = c(0.7, -0.1, 4),heights = c(0.9, 0.1, -0.1, 4, 1))

(0)

相关推荐

  • python聚类分析实现电商用户细分(基于RFM用户价值分析模型)

    背景 聚类分析在机器学习领域属于无监督学习的一种,能够根据一些特征对样本数据进行分类.使用聚类分析分完的类具有"类中相似,类间区别"的特点.RFM模型是非常常见的分析用户价值的方法 ...

  • 浅谈生态学领域科研图表绘制的方向和未来

    摘要 统计和绘图之间界限越来越模糊: 组合图形是趋势: 示意图或者照片图像和图表逐渐结合: R语言继续发光发热.ggplot是核心. 写在前面 在近年来,随着作图工具发展,我们越来越自由,更加可以随心 ...

  • 用TSNE进行数据降维并展示聚类结果

    TSNE提供了一种有效的数据降维方式,让我们可以在2维或3维的空间中展示聚类结果. #-*- coding: utf-8 -*-from __future__ import unicode_liter ...

  • ComplexHeatmap|绘制单个热图-I

    ComplexHeatmap可以绘制很复杂的热图,能满足日常以及文章所需,本次先简单的介绍单个热图绘制的内容. 单个热图由热图主体和热图组件组成.其中主体可分为行和列:组件可以是标题.树状图.矩阵名称 ...

  • 【知识分享】为什么你推敲平面方案,总是考虑不全面,因为你不画气泡图!

    做平面方案布局最重要是要有全局观 从宏观视角全盘考虑整个空间的布局划分和功能分配 很多设计师做方案提笔上来就抓的很细 一步一步的推敲,忽视了整体全局的分配 往往会造成考虑不全面的问题 功能较多的空间, ...

  • 为什么你推敲平面方案,总是考虑不全面,因为你不画气泡图!

    来源:设计师的脑细胞 微信公众号ID : sjnaoxibao 做平面方案布局最重要是要有全局观 从宏观视角全盘考虑整个空间的布局划分和功能分配 很多设计师做方案提笔上来就抓的很细 一步一步的推敲,忽 ...

  • 他画的驴能踢死人!

    ◆ ◆ ◆ 齐白石画虾 徐悲鸿画马 黄胄画驴 这些都是画家的绝技 那么多高大上的东西 为什么黄胄偏偏选择画驴? 20多岁的黄胄已在绘画道路有所成就 上天又给了他一次'深造'的机会 赶上了文革 过上了卖 ...

  • E 自然纹理 1水渍画(动物)

    这组自然纹理,是浴盆中的风景,来自浴盆水中的偶然发现.有一段时间,区域自来水管道被挖断,等重新修好正常供水,水渍较多,我发现其中的纹理很好看,再用滴水略加雕琢,形成了这个有动物主题形象的系列.所谓苦中 ...

  • 彩墨牡丹这样画

    <睛>画法步骤 步骤一:墨蓝写叶,近浓远淡,浓墨勾叶筋.(花头参照牡丹花头画法) 步骤二:浓淡墨写老枝,草绿蘸朱红写嫩梗. 步骤三:草绿蘸朱红写姨婆梗,老枝的节处撞以淡石绿水. 步骤四:后 ...

  • 陈辉:字与画的逻辑关系

           中国文字是从新石器时代远古人类的图画中分流而来的,进而演变成为象形文字,再经过抽象提炼,以线条为主要艺术表达形态,是独立发展成型的一个艺术门类.书法和绘画之间因为很多的共性,始终存在着相 ...

  • 音画 烛光里的妈妈

    音画 烛光里的妈妈

  • 他画的荔枝活色生香,堪称一绝!

    容漱石  荔枝小鸟 最近去市场,看到新鲜的荔枝上市了,看着那鲜嫩多汁的果子,真令人垂涎欲滴! 连吃货苏轼也说:日啖荔枝三百颗,不辞长作岭南人. 说到岭南的荔枝,我们得来看看这位岭南画家容漱石的作品,这 ...

  • 赏析|沈周60幅水墨山水画欣赏,形神兼备,文人画经典之作

    沈周(1427年--1509年)字启南,号石田,江苏常州人.出身世代文人之家,其祖父.父亲都擅长诗画. 明 沈周 杖藜远眺纸本 其艺术成就主要表现在水墨山水画方面.他能从多方面摹习古人画作,又加入了自 ...