首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >掌握单细胞动态:手把手教你RNA速率分析(附代码)

掌握单细胞动态:手把手教你RNA速率分析(附代码)

作者头像
天意生信云
发布2025-06-08 16:23:28
发布2025-06-08 16:23:28
8080
举报

RNA 速率分析概述

RNA 速率分析利用已剪接 mRNA(spliced mRNA)和未剪接 mRNA(unspliced mRNA)之间的比例,推断基因表达的瞬时变化速率,从而预测细胞在转录层面的未来状态。简单来说,它能从细胞的“快照”中,看到它“走向何方”。

为什么要做 RNA 速率分析?

  • 揭示细胞发展轨迹: 描绘细胞分化、重编程或疾病进展中的动态路径。
  • 识别过渡态和中间群体: 捕捉传统方法难以识别的短暂细胞状态。
  • 推断调控关系: 帮助理解基因表达的动态调控网络。

怎么做 RNA 速率分析?

RNA 速率分析的核心在于获取并比较已剪接和未剪接 mRNA 的表达量。这通常需要:

  • 特定文库制备: 如 10x Genomics v3 化学试剂盒,以区分剪接和未剪接的 RNA。
  • 数据量化: 使用工具(如 velocyto)对已剪接和未剪接的计数进行量化。
  • 计算分析: 运用专门的算法(如 velocyto.R 包),结合细胞的降维和聚类信息,计算并可视化 RNA 速率。

实战演练:手把手教你进行 RNA 速率分析

接下来我们将基于R语言完成RNA速率分析:

准备环境——加载必要工具包

代码语言:javascript
复制
# 1. 加载必要包 --------------------------------------------------------------
suppressPackageStartupMessages({
  library(Seurat)       # 单细胞数据分析基石
  library(SeuratDisk)   # 用于处理 h5ad 和 loom 文件
  library(SeuratWrappers) # Seurat 的辅助包,提供与其他工具的接口
  library(velocyto.R)   # RNA 速率分析的核心算法包
  library(ggplot2)      # 强大的绘图工具
  library(Matrix)       # 处理稀疏矩阵
  library(loomR)        # 直接读取 loom 文件
  library(patchwork)    
})

数据导入

RNA 速率分析通常从 .loom 文件开始,这种文件格式高效地存储了已剪接和未剪接的计数信息。我选择了10x官网提供的示例数据,下载地址:(https://cf.10xgenomics.com/supp/cell-exp/neutrophils/WB_Lysis_3p_Introns_8kCells.loom)。Seurat官网提供的数据demo不适用于RNA速率分析,因为数据是剪接之后的。

代码语言:javascript
复制
# 2. 读取loom文件并创建Seurat对象 --------------------------------------------
process_loom <- function(loom_path) {
# 尝试使用SeuratDisk直接读取
if (requireNamespace("SeuratDisk", quietly = TRUE)) {
    tryCatch({
      cat("Attempting to read loom file with SeuratDisk...\n")
      seurat_obj <- LoadLoom(loom_path,
                             assay = "RNA",
                             layers = c("spliced", "unspliced"),
                             verbose = FALSE)
      cat("Successfully loaded loom with SeuratDisk\n")
      # 确保 "counts" 层设置为 "spliced" 数据
      if ("spliced" %in% Layers(seurat_obj[["RNA"]])) {
        LayerData(seurat_obj, assay = "RNA", layer = "counts") <- LayerData(seurat_obj, assay = "RNA", layer = "spliced")
      }
      # 检查 "unspliced" 层是否存在
      if ("unspliced" %in% Layers(seurat_obj[["RNA"]])) {
        cat("Unspliced layer loaded by LoadLoom\n")
      } else {
        stop("Unspliced layer not found after LoadLoom")
      }
      return(seurat_obj)
    }, error = function(e) {
      cat("SeuratDisk loading failed, using manual method...\n")
    })
  }
# 手动读取方法(当SeuratDisk无法加载时备用)
  cat("Reading loom file manually...\n")
  loom <- connect(loom_path, mode = "r", skip.validate = TRUE)
  spliced <- t(loom[["layers/spliced"]][, ])
  unspliced <- t(loom[["layers/unspliced"]][, ])
  cell_ids <- loom[["col_attrs/CellID"]][]
  gene_names <- loom[["row_attrs/Gene"]][]
  colnames(spliced) <- colnames(unspliced) <- cell_ids
  rownames(spliced) <- rownames(unspliced) <- gene_names
  loom$close_all()
  cat("Creating Seurat object...\n")
  seurat_obj <- CreateSeuratObject(
    counts = spliced,
    assay = "RNA",
    project = "RNA_velocity",
    min.cells = 3,
    min.features = 200
  )
# 添加 "unspliced" 作为 "RNA" assay 的一个层
  LayerData(seurat_obj, assay = "RNA", layer = "unspliced") <- unspliced
return(seurat_obj)
}

数据检查

在深入分析之前,先定义一个实用的小函数,帮助我们可视化单个基因的已剪接和未剪接计数,直观感受它们之间的关系。

代码语言:javascript
复制
# 3. 自定义函数:绘制剪接与未剪接计数散点图 ---------------------------------
plot_spliced_unspliced <- function(seurat_obj, gene) {
# 从 "RNA" assay 中提取 spliced 和 unspliced 数据
  spliced <- GetAssayData(seurat_obj, assay = "RNA", layer = "counts")[gene, ]
  unspliced <- GetAssayData(seurat_obj, assay = "RNA", layer = "unspliced")[gene, ]
# 创建数据框
  df <- data.frame(spliced = spliced, unspliced = unspliced)
# 使用 ggplot2 创建散点图,应用 log 变换以处理稀疏数据
  p <- ggplot(df, aes(x = spliced + 1, y = unspliced + 1)) +
    geom_point(alpha = 0.5) +
    scale_x_log10() +
    scale_y_log10() +
    labs(title = gene, x = "Spliced + 1", y = "Unspliced + 1") +
    theme_minimal()
return(p)
}

数据预处理

这一步将对数据进行过滤、标准化、特征选择、降维和聚类。

代码语言:javascript
复制
# 4. 数据预处理 --------------------------------------------------------------
preprocess_data <- function(seurat_obj) {
  cat("Preprocessing data...\n")
  DefaultAssay(seurat_obj) <- "RNA"
# 保存 unspliced 数据以防被覆盖
if ("unspliced" %in% Layers(seurat_obj[["RNA"]])) {
    unspliced_data <- LayerData(seurat_obj, assay = "RNA", layer = "unspliced")
  } else {
    stop("Unspliced layer missing before preprocessing")
  }
# 基础过滤
  seurat_obj <- subset(seurat_obj, subset = nFeature_RNA > 200 & nCount_RNA < 50000)
# 标准化和特征选择
  seurat_obj <- NormalizeData(seurat_obj)
  seurat_obj <- FindVariableFeatures(seurat_obj, selection.method = "vst", nfeatures = 3000)
  seurat_obj <- ScaleData(seurat_obj, features = rownames(seurat_obj))
# 降维与聚类
  seurat_obj <- RunPCA(seurat_obj, npcs = 50, verbose = FALSE)
  seurat_obj <- FindNeighbors(seurat_obj, dims = 1:30)
  seurat_obj <- FindClusters(seurat_obj, resolution = 0.8)
  seurat_obj <- RunUMAP(seurat_obj, dims = 1:30, n.neighbors = 30, min.dist = 0.3)
# 恢复 unspliced 层(重要!确保 unspliced 数据在处理后依然存在)
  LayerData(seurat_obj, assay = "RNA", layer = "unspliced") <- unspliced_data
  cat("Unspliced layer restored after preprocessing\n")
return(seurat_obj)
}

:在 Seurat 的预处理过程中,有些函数可能会默认修改或移除数据层。为了确保 RNA 速率分析所需的 unspliced 层不丢失,我们在函数开始时保存了它,并在结束时恢复它。

计算 RNA 速率

代码语言:javascript
复制
# 5. RNA速率分析 --------------------------------------------------------------
run_velocity <- function(seurat_obj) {
  cat("Running RNA velocity analysis...\n")
# 打印可用层名以便调试
  cat("Layers in RNA assay:", Layers(seurat_obj[["RNA"]]), "\n")
# 从 "RNA" assay 中获取 spliced 和 unspliced 数据
  emat <- as.matrix(GetAssayData(seurat_obj, assay = "RNA", layer = "counts"))      # 已剪接数据
  nmat <- as.matrix(GetAssayData(seurat_obj, assay = "RNA", layer = "unspliced"))  # 未剪接数据
# UMAP 坐标(嵌入),用于后续可视化
  umap_coords <- Embeddings(seurat_obj, "umap")
# 计算 PCA 坐标上的欧几里得距离矩阵,用于构建细胞间的邻近关系
  pca_coords <- Embeddings(seurat_obj, "pca")[, 1:30]  # 使用前30个主成分
  cell_dist <- dist(pca_coords, method = "euclidean")
# 执行速度分析
  rvel <- gene.relative.velocity.estimates(
    emat = emat,
    nmat = nmat,
    deltaT = 1,          # 时间步长,通常设为1
    kCells = 25,         # 用于局部估计的邻近细胞数
    fit.quantile = 0.02, # 拟合模型时使用的分位数
    cell.dist = cell_dist, # 细胞距离矩阵
    verbose = TRUE
  )
# 将结果写入 Seurat 对象的 @misc 槽,方便后续调用
  seurat_obj@misc[["RunVelocity"]] <- rvel
return(seurat_obj)
}

参数详解:

  • emat 和 nmat:分别对应已剪接和未剪接的计数矩阵。
  • deltaT模型中的时间步长,通常保持默认值 1。
  • kCells:用于计算局部速度估计的最近邻细胞数。这个参数会影响速度向量的平滑度和局部性,可以根据数据集大小和细胞异质性进行调整。
  • fit.quantile:用于拟合稳态直线的基因表达分位数,通常较小的值(如 0.02-0.05)效果较好。

可视化与保存

代码语言:javascript
复制
# 6. 可视化与保存结果 --------------------------------------------------------
visualize_results <- function(seurat_obj, output_dir = "results") {
  cat("Visualizing results...\n")
if (!dir.exists(output_dir)) dir.create(output_dir)
# 保存 Seurat 对象,包含所有分析结果
  saveRDS(seurat_obj, file.path(output_dir, "velocity_seurat.rds"))
# 1. UMAP 聚类图:展示细胞群体分布
  pdf(file.path(output_dir, "umap_clusters.pdf"), width = 8, height = 6)
print(DimPlot(seurat_obj, reduction = "umap", label = TRUE) +
          ggtitle("Cell Clusters"))
  dev.off()
# 2. RNA 速率矢量图:细胞命运的动态轨迹
  pdf(file.path(output_dir, "rna_velocity.pdf"), width = 10, height = 8)
  ident.colors <- scales::hue_pal()(length(levels(seurat_obj)))
  names(ident.colors) <- levels(seurat_obj)
  cell.colors <- ident.colors[Idents(seurat_obj)]
  names(cell.colors) <- colnames(seurat_obj)
  show.velocity.on.embedding.cor(
    emb = Embeddings(seurat_obj, "umap"),
    vel = seurat_obj@misc[["RunVelocity"]],
    n = 300,             # 在图中显示的细胞子集数量(为避免过于拥挤)
    scale = "sqrt",      # 矢量长度的缩放方式
    cell.colors = ac(cell.colors, alpha = 0.5), # 细胞颜色及透明度
    cex = 0.8,           # 细胞点的大小
    arrow.scale = 3,     # 箭头长度的缩放因子
    show.grid.flow = TRUE, # 是否显示网格流线
    grid.n = 50,         # 网格密度
    main = "RNA Velocity"
  )
  dev.off()
# 3. 剪接/未剪接基因图:展示部分高变基因的剪接状态
  pdf(file.path(output_dir, "spliced_vs_unspliced.pdf"), width = 9, height = 7)
  var_genes <- VariableFeatures(seurat_obj)
  genes_to_plot <- if (length(var_genes) > 20) sample(var_genes, 9) else var_genes
# 使用自定义函数生成并排列散点图
  plots <- lapply(genes_to_plot, function(gene) plot_spliced_unspliced(seurat_obj, gene))
  p <- wrap_plots(plots, ncol = 3) # 使用 patchwork 组合多图
print(p)
  dev.off()
  cat("Results saved to:", output_dir, "\n")
}

可视化解读:

  • UMAP 聚类图: 这是你的细胞群体的静态分布,帮助你理解细胞的整体异质性。
图片
图片
  • RNA 速率矢量图: 这是核心输出!在 UMAP 降维图上叠加了一系列箭头,每个箭头代表一个或一组细胞的预测转录方向。箭头的方向指明了细胞未来可能分化的方向,而箭头的长度则反映了变化的“速度”。你会看到细胞从一个聚类“流向”另一个聚类的趋势,就像河流的走向一般。
图片
图片
  • 剪接/未剪接基因图: 帮助你检查特定基因的剪接状态,验证其是否符合理论预期。
图片
图片

结语

通过 RNA 速率分析,我们能够从全新的视角审视单细胞数据,揭示细胞状态转变的内在动力学。它不仅能帮助我们理解正常的发育和分化过程,还能在疾病研究中提供宝贵的线索,例如肿瘤进展、免疫细胞活化等。

当然,RNA 速率分析也有其局限性,例如它主要反映的是转录水平的动态,不直接涵盖译或蛋白质修饰等更复杂的调控。但作为一种强大的探索性工具,它无疑为我们打开了通往细胞命运深处的一扇窗。

现在,你已经掌握了 RNA 速率分析的基本流程。快去探索你的细胞数据,揭示它们隐藏的“未来”吧!在你的科研征程中,RNA 速率分析或许就是那把解开细胞命运之谜的钥匙。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-05-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 BioOmics 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • RNA 速率分析概述
  • 为什么要做 RNA 速率分析?
  • 怎么做 RNA 速率分析?
  • 实战演练:手把手教你进行 RNA 速率分析
    • 准备环境——加载必要工具包
    • 数据导入
    • 数据检查
    • 数据预处理
    • 计算 RNA 速率
    • 可视化与保存
    • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档