可视化 | 单细胞火山图 函数

文章介绍了使用Seurat包进行单细胞转录组数据的分析,包括PBMC数据集的DEG(差异表达基因)检测和multiVolcanoPlot函数的应用,展示了如何识别和可视化显著变化的基因标记。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 效果图

(a) PBMC 3k

DimPlot(pbmc, label = T)
pbmc.markers <- FindAllMarkers(pbmc, min.pct = 0.25, logfc.threshold = 0.25)
pbmc.markers %>% group_by(cluster) %>% top_n(n = 2, wt = abs(avg_log2FC) )

DEG = pbmc.markers
multiVolcanoPlot(DEG, color.pals)

在这里插入图片描述

(b) PBMC 2

scObj.markers.time <- FindAllMarkers(
  (function(){
    scObj2=scObj;
    Idents(scObj2)="time"
    scObj2
  })(), 
  only.pos = F, min.pct = 0.25, logfc.threshold = 0.25)

# 画图
#multiVolcanoPlot(DEG, color.pals)
#multiVolcanoPlot(scObj.markers.time)
#multiVolcanoPlot(scObj.markers.time, onlyAnnotateUp = F)

multiVolcanoPlot(scObj.markers.time, top_marker = 10, onlyAnnotateUp = F)

在这里插入图片描述

2. 源代码

# > head(DEG)
#              p_val avg_log2FC pct.1 pct.2     p_val_adj     cluster  gene label
#RPS12 1.273332e-143  0.7298951 1.000 0.991 1.746248e-139 Naive CD4 T RPS12    Up
#RPS6  6.817653e-143  0.6870694 1.000 0.995 9.349729e-139 Naive CD4 T  RPS6    Up
#


color.pals = c("#DC143C","#0000FF","#20B2AA","#FFA500","#9370DB","#98FB98","#F08080","#1E90FF","#7CFC00","#FFFF00",
               "#808000","#FF00FF","#FA8072","#7B68EE","#9400D3","#800080","#A0522D","#D2B48C","#D2691E","#87CEEB","#40E0D0","#5F9EA0",
               "#FF1493","#0000CD","#008B8B","#FFE4B5","#8A2BE2","#228B22","#E9967A","#4682B4","#32CD32","#F0E68C","#FFFFE0","#EE82EE",
               "#FF6347","#6A5ACD","#9932CC","#8B008B","#8B4513","#DEB887")

#
#' multi volcano plot for scRNA-seq
#' @version 0.2 change legend order
#'
#' @param dat Seurat FindAllMarkers returns, must set only.pos = F;
#' @param color.arr color list, default same as Seurat
#' @param onlyAnnotateUp only annote gene symbols for up genes
#' @param log2Foldchang threshold for annotation
#' @param adjp  threshold for annotation
#' @param top_marker gene number for annotation
#' @param max_overlaps annotation label overlapping
#'
#' @return ggplot2 obj
#' @export
#'
#' @examples
multiVolcanoPlot = function(dat, color.arr=NULL, onlyAnnotateUp=T,
                            log2Foldchang=0.58, adjp=0.05, top_marker=5, 
                            max_overlaps=10, width=0.9){
  library(dplyr)
  library(ggrepel)
  # set default color list
  if(is.null(color.arr)){
    len = length(unique(dat$cluster))
    color.arr=scales::hue_pal()(len)
  }
  
  dat.plot <- dat %>% mutate(
    "significance"=case_when(p_val_adj < adjp & avg_log2FC >= log2Foldchang  ~ 'Up',
                             p_val_adj < adjp & avg_log2FC <= -log2Foldchang  ~ 'Down',
                             TRUE ~ 'None'))
  tbl = table(dat.plot$significance)
  print( tbl )
  background.dat <- data.frame(
    dat.plot %>% group_by(cluster) %>% filter(avg_log2FC>0) %>%
      summarise("y.localup"=max(avg_log2FC)),
    dat.plot %>% group_by(cluster) %>% filter(avg_log2FC<=0) %>%
      summarise("y.localdown"=min(avg_log2FC)),
    x.local=seq(1:length(unique(dat.plot$cluster)))
  ) %>% select(-cluster.1)
  #names(background.dat)
  #head(background.dat)
  #dim(background.dat)
  
  #
  x.number <- background.dat %>% select(cluster, x.local)
  dat.plot <- dat.plot%>% left_join(x.number,by = "cluster")
  #names(dat.plot)
  #head(dat.plot)
  
  #selecting top-up and top-down proteins
  dat.marked.up <- dat.plot %>% filter(significance=="Up") %>%
    group_by(cluster) %>% arrange(-avg_log2FC) %>%
    top_n(top_marker,abs(avg_log2FC))
  dat.marked.down <- dat.plot %>% filter(significance=="Down") %>%
    group_by(cluster) %>% arrange(avg_log2FC) %>%
    top_n(top_marker,abs(avg_log2FC))
  dat.marked <- dat.marked.up %>% bind_rows(dat.marked.down)
  #referring group information data
  dat.infor <- background.dat %>%
    mutate("y.infor"=rep(0,length(cluster)))
  #names(dat.infor)
  #dim(dat.infor)
  #head(dat.infor)
  
  ##plotting:
  #setting color by loading local color schemes
  vol.plot <- ggplot()+
    # background
    geom_col(background.dat,mapping=aes(x.local, y.localup),
             fill="grey80", alpha=0.2, width=0.9, just = 0.5)+
    geom_col(background.dat,mapping=aes(x.local,y.localdown),
             fill="grey80", alpha=0.2, width=0.9, just = 0.5)+
    # point plot
    geom_jitter(dat.plot, mapping=aes(x.local, avg_log2FC, #x= should be number, Not string or factor
                                      color=significance),
                size=0.8, width = 0.4, alpha= 1)+
    scale_color_manual(name="significance", 
                       breaks = c('Up', 'None', 'Down'),
                       values = c("#d56e5e","#cccccc", "#5390b5")) + #set color for: Down None   Up
    geom_tile(dat.infor, mapping=aes(x.local, y.infor), #x axis color box
              height = log2Foldchang*1.3,
              fill = color.arr[1:length(unique(dat.plot$cluster))],
              alpha = 0.5,
              width=width) +
    labs(x=NULL,y="log2 Fold change")+
    geom_text(dat.infor, mapping=aes(x.local,y.infor,label=cluster))+
    # Down is not recommend, not meaningful, hard to explain; so prefer dat.marked.up to dat.marked
    ggrepel::geom_label_repel(data=if(onlyAnnotateUp) dat.marked.up else dat.marked, #gene symbol, of up group default
                              mapping=aes(x=x.local, y=avg_log2FC, label=gene),
                              force = 2, #size=2,
                              #max.overlaps = max_overlaps,
                              label.size = 0, #no border
                              fill="#00000000", #box fill color
                              seed = 233,
                              min.segment.length = 0,
                              force_pull = 2,
                              box.padding = 0.1,
                              segment.linetype = 3,
                              #segment.color = 'black',
                              #segment.alpha = 0.5,
                              #direction = "x", #line direction
                              hjust = 0.5)+
    annotate("text", x=1.5, y=max(background.dat$y.localup)+1,
             label=paste0("|log2FC|>=", log2Foldchang, " & FDR<", adjp))+
    theme_classic(base_size = 12)+
    
    theme(
      axis.title = element_text(size = 13, color = "black"),
      axis.text = element_text(size = 15, color = "black"),
      axis.line.y = element_line(color = "black", size = 0.8),
      #
      axis.line.x = element_blank(), #no x axis line
      axis.ticks.x = element_blank(), #no x axis ticks
      axis.title.x = element_blank(), #
      axis.text.x = element_blank(),
      #
      legend.spacing.x = unit(0.1,'cm'),
      legend.key.width = unit(0.5,'cm'),
      legend.key.height = unit(0.5,'cm'),
      legend.background = element_blank(),
      legend.box = "horizontal",
      legend.position = c(0.13, 0.77),legend.justification = c(1,0)
    )+
    guides( #color = guide_legend( override.aes = list(size=5) ), #legend circle size
      color=guide_legend( override.aes = list(size=5), title="Change")
    )
  #guides(fill=guide_legend(title="Change"))+ #change legend title
  vol.plot
}
<think>好的,我现在需要帮助用户解决他们在使用Seurat包进行单细胞转录组数据分析的问题。用户的具体需求是加载10X Genomics数据,强制使用Gene Symbol作为特征标识,分析四个不同组别(正常喉黏膜上皮细胞N、原位癌T、癌缘R、淋巴结L)的差异基因,进行可视化,并将差异基因与喉癌癌症干细胞相关基因取交集,再可视化。同时用户还提供了引用资料,我需要参考这些内容来构建回答。 首先,我要确认用户的数据文件是否正确,他们提到有barcodes.tsv.gz、features.tsv.gz和matrix.mtx.gz,这些都是标准的10X数据格式。根据引用[1]中的描述,这些文件分别包含细胞ID、基因注释和表达矩阵。所以,第一步应该是如何正确加载这些数据到Seurat对象中。用户强调要强制使用Gene Symbol,这可能是因为features.tsv.gz文件中可能有多个标识符,比如Gene ID和Symbol,而默认情况下Seurat可能会使用ID,需要指定使用Symbol。 接下来,用户需要分析四个组的差异基因。根据引用[2],Seurat的数据预处理步骤包括数据过滤、标准化、特征选择、降维等。用户可能需要先进行这些预处理步骤,然后进行分组差异分析。但用户的问题中没有明确是否已经完成这些步骤,所以可能需要指导用户完成整个流程,包括数据加载、预处理、差异分析、可视化和交集分析。 在差异基因分析方面,用户可能需要使用Seurat的FindMarkers函数,针对每个组别进行比较。例如,比较T vs N,R vs N,L vs N,或者其他组合。然后,提取每个比较中的差异基因,并保存结果。 关于可视化,用户可能需要火山、热、UMAP等。根据引用[2],tidyverse和patchwork包可以用于数据整理和形组合,可能需要使用这些工具来生成高质量的可视化结果。 然后,用户需要将差异基因与喉癌癌症干细胞相关基因取交集。这里需要用户提供一个干细胞相关基因列表,或者示例代码中假设存在一个名为stem_genes的向量。这部分可能需要用户自行提供,或者在代码中注释说明需要用户输入。 此外,用户可能需要保存结果,比如差异基因列表、像文件等,所以代码中需要包含保存步骤,如write.csv和ggsave。 在引用方面,需要根据用户提供的引用[1]、[2]、[3]来支持回答。例如,引用[2]提到如何创建Seurat对象和数据过滤,引用[3]解释了Seurat对象的结构,这些都可以在回答中适当引用,以增强可靠性。 现在需要考虑可能的问题点:如何正确指定Gene Symbol,因为features.tsv.gz通常有两列,默认Seurat可能使用第一列作为基因ID,第二列作为Symbol。用户需要强制使用Symbol作为特征名,所以在加载数据时,需要设置gene.column=2。例如,在Read10X函数中指定,或者在创建Seurat对象时设置。 另一个问题是数据预处理步骤是否正确,包括QC过滤、标准化、PCA、聚类等。用户的问题可能已经知道这些步骤,但需要确保代码中包含必要的步骤,如NormalizeData、FindVariableFeatures、ScaleData、RunPCA、FindNeighbors、FindClusters、RunUMAP等,以便后续的差异分析。 差异分析部分,用户需要根据样本的分组信息,在metadata中设置正确的分组变量,例如orig.ident或其他列。可能需要用户提前将细胞分配到N、T、R、L四个组别中。如果用户的metadata中没有这个信息,需要指导用户如何添加,比如根据细胞ID的前缀或其他方式。例如,假设每个组的细胞barcode有特定的前缀,可以通过substring提取并添加到metadata中。 假设用户的metadata中已经有一个名为"group"的列,包含N、T、R、L四个类别,那么差异分析可以通过设置ident.1和ident.2来进行比较。例如,比较T组与N组的差异基因。 可视化部分,火山可以使用EnhancedVolcano包,热使用DoHeatmap函数,UMAP使用DimPlot。此外,交集的可视化可以使用VennDiagram或UpSetR包,但需要安装这些包。 最后,保存结果时,需要确保路径正确,可能建议用户设置合适的工作目录,或者使用相对路径。 需要检查代码的正确性,例如在FindMarkers函数中是否正确指定了组别,是否进行了适当的过滤(如logfc.threshold,min.pct等参数)。同时,差异基因的交集可能需要使用Reduce函数来处理多个比较的结果。 总结步骤: 1. 加载数据,强制使用Gene Symbol。 2. 数据预处理和质量控制。 3. 降维和聚类。 4. 差异基因分析。 5. 可视化差异结果。 6. 与干细胞基因取交集并可视化。 7. 保存结果。 需要确保每一步都有对应的代码,并且注释清晰,用户能够理解每个步骤的作用。同时,引用相关的引用资料,比如创建Seurat对象参考引用[2],对象结构参考引用[3]。</think>以下为基于Seurat包的单细胞数据分析流程,包含强制使用Gene Symbol的10X数据加载、差异分析和可视化实现方法: ```r # 加载所需R包 library(Seurat) library(tidyverse) library(patchwork) library(EnhancedVolcano) # 1. 数据加载与预处理 ---------------------------------------------------------- # 强制使用Gene Symbol作为特征名(gene.column=2) data_dir <- "path/to/10X_data/" # 替换为实际数据路径 matrix_data <- Read10X(data.dir = data_dir, gene.column = 2) seurat_obj <- CreateSeuratObject(counts = matrix_data, project = "LaryngealCancer", min.cells = 3, min.features = 200)[^2] # 添加样本分组信息(根据实际情况调整分组标识) seurat_obj$group <- case_when( str_detect(colnames(seurat_obj), "^N_") ~ "Normal", str_detect(colnames(seurat_obj), "^T_") ~ "Tumor", str_detect(colnames(seurat_obj), "^R_") ~ "Margin", str_detect(colnames(seurat_obj), "^L_") ~ "LymphNode" )[^3] # 2. 数据标准化与降维 --------------------------------------------------------- seurat_obj <- NormalizeData(seurat_obj) seurat_obj <- FindVariableFeatures(seurat_obj) seurat_obj <- ScaleData(seurat_obj) seurat_obj <- RunPCA(seurat_obj) seurat_obj <- RunUMAP(seurat_obj, dims = 1:30) # 3. 差异基因分析 ------------------------------------------------------------ Idents(seurat_obj) <- "group" diff_genes <- FindAllMarkers(seurat_obj, logfc.threshold = 0.25, min.pct = 0.1, only.pos = TRUE) # 保存差异分析结果 write.csv(diff_genes, "Differential_Genes.csv") # 4. 可视化分析 -------------------------------------------------------------- # 可视化UMAP聚类 p1 <- DimPlot(seurat_obj, reduction = "umap", group.by = "group") + scale_color_manual(values = c("#1F78B4","#EE2B2B","#33A02C","#6A3D9A")) # 热可视化前5个差异基因 top5_genes <- diff_genes %>% group_by(cluster) %>% top_n(5, avg_log2FC) p2 <- DoHeatmap(seurat_obj, features = top5_genes$gene) + theme(axis.text.y = element_text(size = 6)) # 组合可视化 (p1 | p2) + plot_annotation(title = "单细胞转录组分析结果") ggsave("Analysis_Visualization.pdf", width = 15, height = 7) # 5. 基因集交集分析 ---------------------------------------------------------- # 假设已有干细胞相关基因列表 stem_genes <- c("SOX2", "NANOG", "OCT4", "CD44", "ALDH1A1") # 示例基因 # 获取各组差异基因 normal_genes <- diff_genes %>% filter(cluster == "Normal") %>% pull(gene) tumor_genes <- diff_genes %>% filter(cluster == "Tumor") %>% pull(gene) # 计算交集 common_genes <- intersect(stem_genes, tumor_genes) # 可视化交集(需安装VennDiagram包) VennDiagram::venn.diagram( x = list(Stem = stem_genes, Tumor = tumor_genes), filename = "Gene_Overlap.tiff", fill = c("#E69F00", "#56B4E9") ) ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值