非编码 RNA(ceRNA/lncRNA/circRNA)分析完整流程:从数据下载到功能验证(含代码模板)

非编码 RNA(ncRNA)是基因组中不编码蛋白质的 RNA 分子,其中 lncRNA(长链非编码 RNA)、circRNA(环状 RNA)及由其构成的 ceRNA(内源竞争 RNA)网络,已成为肿瘤发生发展、代谢调控、免疫应答等领域的研究热点。不同于编码基因分析,ncRNA 具有 "序列保守性低、功能机制复杂、依赖调控网络解析" 的特点,需一套从数据获取到实验验证的完整分析体系。

本文结合生信实战场景,系统拆解 lncRNA/circRNA/ceRNA 分析的全流程,涵盖数据下载与质控→预处理与定量→差异表达分析→ceRNA 网络构建→功能富集→实验验证 6 大核心环节,提供 Python、R、Shell 全套代码模板,适配 GEO、TCGA 等公共数据集及自建测序数据,助力研究者快速落地 ncRNA 相关研究。

一、分析前准备:核心概念与工具清单

在正式分析前,需明确三类 ncRNA 的核心特性及分析逻辑,避免流程偏差:

  • lncRNA:长度>200nt 的线性 ncRNA,通过吸附 miRNA、调控染色质修饰等发挥作用,分析核心是 "差异表达 + 靶标预测 + 功能关联"。
  • circRNA:由前体 mRNA 反向剪接形成的环状分子,稳定性高,核心功能是作为 ceRNA 吸附 miRNA,分析需重点关注 "环状结构识别 + miRNA 结合位点预测"。
  • ceRNA 网络:核心逻辑是 "ceRNA(lncRNA/circRNA)与 mRNA 竞争结合同一 miRNA",通过调控 miRNA 浓度间接影响 mRNA 表达,分析核心是 "分子间相互作用验证 + 网络拓扑分析"。

必备工具与环境配置

分析环节 核心工具 语言 / 平台 核心功能
数据下载 SRA Toolkit、TCGAbiolinks Shell/R 下载 GEO/TCGA 原始测序数据
质量控制 FastQC、MultiQC Shell 评估 FASTQ 数据质量(碱基质量、接头污染)
序列比对 STAR、HISAT2 Shell 基因组比对,获取比对 BAM 文件
转录本组装 StringTie、Cufflinks Shell 组装转录本,识别新 lncRNA/circRNA
定量分析 Salmon、FeatureCounts Shell/R 计算基因 / 转录本表达量(count 矩阵)
差异分析 DESeq2、edgeR、limma R 筛选差异表达 lncRNA/circRNA/mRNA/miRNA
靶标预测 TargetScan、miRanda、RNAhybrid Python/R 预测 miRNA 与 ceRNA/mRNA 的结合位点
网络构建 Cytoscape、igraph R/Python 构建 ceRNA 调控网络,拓扑分析
功能富集 clusterProfiler、clusterProfiler2 R GO/KEGG 富集、GSEA 分析
可视化 ggplot2、pheatmap、ComplexHeatmap R 表达热图、火山图、富集气泡图

环境配置建议:使用 Conda 统一管理环境,避免依赖冲突

bash 复制代码
# 创建 ncRNA 分析专用环境
conda create -n ncRNA_analysis python=3.8 R=4.2.0 -y
conda activate ncRNA_analysis

# 安装 Shell 工具
conda install -c bioconda fastqc multiqc star hisat2 stringtie salmon featurecounts sra-tools -y

# 安装 R 包(通过 R 终端执行)
install.packages(c("tidyverse", "pheatmap", "ggplot2"))
if (!require("BiocManager", quietly = TRUE))
    install.packages("BiocManager")
BiocManager::install(c("DESeq2", "edgeR", "limma", "clusterProfiler", "org.Hs.eg.db", "TCGAbiolinks"))

# 安装 Python 包
pip install pandas numpy matplotlib seaborn scipy networkx

二、第一步:数据下载与质量控制

ncRNA 分析的数据来源主要分为两类:公共数据库(GEO/TCGA/ENCODE)自建测序数据(FASTQ 格式)。本节重点讲解公共数据下载流程,自建数据可直接跳过下载步骤,进入质控环节。

1. 公共数据下载(GEO/TCGA 示例)

(1)GEO 数据集下载(Shell + SRA Toolkit)

GEO 中原始测序数据以 SRA 格式存储,需用 SRA Toolkit 转换为 FASTQ 格式。示例:下载 GEO 数据集 GSE185997(lncRNA 与肺癌相关的 RNA-seq 数据)

bash 复制代码
# 1. 安装 SRA Toolkit(已通过 Conda 安装可跳过)
# 2. 创建数据存储目录
mkdir -p GSE185997/{sra,fastq,qc}
cd GSE185997

# 3. 下载 SRA 文件(需先在 GEO 页面获取 SRA 访问号,如 SRR19769901、SRR19769902...)
prefetch SRR19769901 SRR19769902 SRR19769903 -O ./sra/

# 4. 转换 SRA 为 FASTQ(单端数据用 --split-3,双端数据自动拆分 R1/R2)
fastq-dump --split-3 ./sra/SRR19769901.sra -O ./fastq/
fastq-dump --split-3 ./sra/SRR19769902.sra -O ./fastq/
fastq-dump --split-3 ./sra/SRR19769903.sra -O ./fastq/
(2)TCGA 数据集下载(R + TCGAbiolinks)

TCGA 提供标准化的 RNA-seq 表达数据(HTSeq-Counts 格式),可直接下载表达矩阵,无需原始数据处理。

R 复制代码
# 加载 R 包
library(TCGAbiolinks)
library(SummarizedExperiment)
library(tidyverse)

# 下载 TCGA-LUAD(肺腺癌)的 RNA-seq 数据(HTSeq-Counts 格式)
query <- GDCquery(
  project = "TCGA-LUAD",
  data.category = "Transcriptome Profiling",
  data.type = "Gene Expression Quantification",
  workflow.type = "HTSeq - Counts"
)

# 执行下载并整理数据
GDCdownload(query, directory = "./TCGA-LUAD")
tcga_data <- GDCprepare(query, directory = "./TCGA-LUAD")

# 提取表达矩阵(行:基因,列:样本)
count_matrix <- assay(tcga_data)
# 提取样本临床信息(用于分组)
sample_info <- colData(tcga_data) %>% as.data.frame() %>% 
  select(sample, sample_type)  # sample_type 包含 Tumor/Normal 分组

2. 数据质量控制(FastQC + MultiQC)

原始测序数据可能存在接头污染、低质量碱基等问题,需通过质控筛选合格数据,避免影响后续分析。

bash 复制代码
# 1. 对所有 FASTQ 文件进行质量评估
fastqc ./fastq/*.fastq -o ./qc/

# 2. 用 MultiQC 整合所有质控结果(生成可视化报告)
multiqc ./qc/ -o ./qc/ --title "GSE185997_QC_Report"

质控结果解读与处理

  • 核心指标:碱基质量值(Q20/Q30 占比≥80% 为合格)、接头污染率、序列长度分布。
  • 问题处理:若存在接头污染,用 Trimmomatic 去除接头;低质量序列用 trimmomatic PE 过滤:
bash 复制代码
# 安装 Trimmomatic
conda install -c bioconda trimmomatic -y

# 双端数据过滤示例(去除接头+低质量碱基)
trimmomatic PE -phred33 \
  ./fastq/SRR19769901_1.fastq ./fastq/SRR19769901_2.fastq \
  ./fastq/clean_SRR19769901_1.fastq ./fastq/unpaired_SRR19769901_1.fastq \
  ./fastq/clean_SRR19769901_2.fastq ./fastq/unpaired_SRR19769901_2.fastq \
  ILLUMINACLIP:TruSeq3-PE.fa:2:30:10 \  # 接头文件路径
  LEADING:3 TRAILING:3 SLIDINGWINDOW:4:15 MINLEN:36  # 过滤参数

三、第二步:数据预处理与定量分析

预处理核心是 "序列比对→转录本组装→表达定量",最终得到 lncRNA、circRNA、mRNA 的表达矩阵(count 或 TPM 格式),为差异分析做准备。

1. lncRNA 预处理与定量(STAR + StringTie + gffcompare)

lncRNA 定量需结合参考基因组注释,识别已知 lncRNA 并预测新 lncRNA。

bash 复制代码
# 1. 下载人类参考基因组(hg38)及注释文件(GENCODE v44)
mkdir -p ./reference/hg38
cd ./reference/hg38
wget https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_44/GRCh38.p14.genome.fa.gz
wget https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_44/gencode.v44.annotation.gtf.gz
gunzip GRCh38.p14.genome.fa.gz gencode.v44.annotation.gtf.gz

# 2. 构建 STAR 索引(仅需执行一次)
STAR --runThreadN 8 \  # 线程数,根据 CPU 核心调整
     --runMode genomeGenerate \
     --genomeDir ./star_index \
     --genomeFastaFiles GRCh38.p14.genome.fa \
     --sjdbGTFfile gencode.v44.annotation.gtf \
     --sjdbOverhang 100  # 与测序读长匹配(通常为读长-1)

# 3. 双端序列比对(以清洁数据为例)
STAR --runThreadN 8 \
     --genomeDir ./reference/hg38/star_index \
     --readFilesIn ./fastq/clean_SRR19769901_1.fastq ./fastq/clean_SRR19769901_2.fastq \
     --outSAMtype BAM SortedByCoordinate \  # 输出排序后的 BAM 文件
     --outFileNamePrefix ./alignment/SRR19769901_ \
     --quantMode TranscriptomeSAM GeneCounts  # 同时输出转录本和基因水平计数

# 4. StringTie 转录本组装(合并所有样本的组装结果)
# 4.1 单个样本组装
stringtie ./alignment/SRR19769901_Aligned.sortedByCoord.out.bam \
          -p 8 -G ./reference/hg38/gencode.v44.annotation.gtf \
          -o ./assembly/SRR19769901.gtf -l SRR19769901  # 转录本前缀

# 4.2 合并所有样本的 GTF 文件(生成整合转录组)
ls ./assembly/*.gtf > assembly_list.txt
stringtie --merge -p 8 -G ./reference/hg38/gencode.v44.annotation.gtf \
          -o ./assembly/merged_transcripts.gtf assembly_list.txt

# 5. gffcompare 注释转录本(区分已知/新转录本)
gffcompare -r ./reference/hg38/gencode.v44.annotation.gtf \
           -G -o ./annotation/merged ./assembly/merged_transcripts.gtf

# 6. 筛选 lncRNA(根据 gffcompare 结果,保留 lncRNA 类型转录本)
# 生成 lncRNA 专属 GTF 文件
awk '$3=="transcript" && $10~/"lncRNA"/ || $10~/"antisense"/ || $10~/"lincRNA"/' \
    ./annotation/merged.annotated.gtf > ./annotation/lncRNA_annotated.gtf

# 7. 定量 lncRNA 表达量(FeatureCounts)
featureCounts -T 8 -t transcript -g gene_id \
              -a ./annotation/lncRNA_annotated.gtf \
              -o ./quantification/lncRNA_counts.txt \
              ./alignment/*.sortedByCoord.out.bam

2. circRNA 预处理与定量(STAR + CIRI2)

circRNA 识别需专门工具(CIRI2/CIRIquant),核心是检测 "反向剪接位点" 以确认环状结构。

bash 复制代码
# 1. 安装 CIRI2(已通过 Conda 安装可跳过)
conda install -c bioconda ciri2 -y

# 2. 用 STAR 比对生成 Chimeric.out.junction 文件(记录剪接位点)
STAR --runThreadN 8 \
     --genomeDir ./reference/hg38/star_index \
     --readFilesIn ./fastq/clean_SRR19769901_1.fastq ./fastq/clean_SRR19769901_2.fastq \
     --outSAMtype BAM SortedByCoordinate \
     --outFileNamePrefix ./alignment/circ_SRR19769901_ \
     --chimSegmentMin 10  # 最小嵌合片段长度

# 3. CIRI2 识别 circRNA(输入 BAM 文件和剪接位点文件)
CIRI2.pl -I ./alignment/circ_SRR19769901_Aligned.sortedByCoord.out.bam \
         -O ./circRNA/SRR19769901_circRNA.txt \
         -F ./reference/hg38/GRCh38.p14.genome.fa \
         -A ./reference/hg38/gencode.v44.annotation.gtf \
         -J ./alignment/circ_SRR19769901_Chimeric.out.junction \
         -T 8

# 4. 合并多个样本的 circRNA 定量结果(生成表达矩阵)
# 用 Python 脚本合并(需提前安装 pandas)
python merge_circRNA_counts.py  # 脚本内容见下方

merge_circRNA_counts.py 脚本

python 复制代码
import pandas as pd
import os

# 获取所有 circRNA 结果文件
circ_files = [f for f in os.listdir("./circRNA/") if f.endswith("_circRNA.txt")]
df_list = []

for file in circ_files:
    sample = file.split("_circRNA.txt")[0]
    # 读取 CIRI2 输出文件(第 1 列:circRNA ID,第 7 列:表达量(junction reads))
    df = pd.read_csv(f"./circRNA/{file}", sep="\t", usecols=[0, 6], names=["circRNA_ID", sample])
    df_list.append(df)

# 合并所有样本(按 circRNA_ID 对齐)
merged_df = df_list[0]
for df in df_list[1:]:
    merged_df = pd.merge(merged_df, df, on="circRNA_ID", how="outer").fillna(0)

# 保存 circRNA 表达矩阵(count 格式)
merged_df.to_csv("./quantification/circRNA_counts.txt", index=False, sep="\t")

3. mRNA 定量(Salmon 快速定量)

mRNA 定量可直接使用 Salmon 进行转录组水平定量,无需比对到基因组,速度更快。

bash 复制代码
# 1. 构建 Salmon 索引(针对 GENCODE 转录组)
wget https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_44/gencode.v44.transcripts.fa.gz
gunzip gencode.v44.transcripts.fa.gz
salmon index -t gencode.v44.transcripts.fa -i ./reference/hg38/salmon_index -k 31

# 2. 定量(双端数据)
salmon quant -i ./reference/hg38/salmon_index \
             -l A \  # 自动识别文库类型
             -1 ./fastq/clean_SRR19769901_1.fastq \
             -2 ./fastq/clean_SRR19769901_2.fastq \
             -o ./quantification/salmon_SRR19769901 \
             --validateMappings  # 验证映射准确性

# 3. 合并所有样本的 mRNA 表达矩阵(TPM 格式)
salmon quantmerge -i ./quantification/salmon_* -o ./quantification/mRNA_tpm.txt --tpm

四、第三步:差异表达分析

差异分析的核心是筛选 "病例组 vs 对照组" 中表达显著变化的分子(lncRNA/circRNA/mRNA/miRNA),常用工具为 DESeq2(适用于 count 数据)、limma(适用于 TPM/FPKM 数据)。

1. 数据预处理(R 脚本)

首先整理表达矩阵和分组信息,确保样本匹配、格式正确。

R 复制代码
library(tidyverse)
library(DESeq2)
library(limma)
library(pheatmap)
library(ggplot2)

# 1. 读取 lncRNA 表达矩阵(count 格式)
lncRNA_counts <- read.delim("./quantification/lncRNA_counts.txt", skip = 1, row.names = 1)
# 去除冗余列(FeatureCounts 输出的第 2-6 列为统计信息)
lncRNA_counts <- lncRNA_counts[, -c(1:5)]
# 简化列名(保留样本 ID 核心部分)
colnames(lncRNA_counts) <- gsub("alignment\\.|_Aligned.sortedByCoord.out.bam", "", colnames(lncRNA_counts))

# 2. 读取分组信息(需手动创建,格式:样本 ID + 分组(case/control))
group_info <- read.delim("./sample_group.txt", row.names = 1)
# 确保分组信息与表达矩阵样本顺序一致
lncRNA_counts <- lncRNA_counts[, rownames(group_info)]

# 3. 过滤低表达基因(保留至少在 3 个样本中表达量≥1 的基因)
keep <- rowSums(lncRNA_counts >= 1) >= 3
lncRNA_counts_filtered <- lncRNA_counts[keep, ]

2. 差异表达分析(DESeq2 示例)

适用于 count 格式数据(lncRNA、circRNA、mRNA 的 count 矩阵)

R 复制代码
# 1. 构建 DESeq2 数据集
dds <- DESeqDataSetFromMatrix(
  countData = lncRNA_counts_filtered,
  colData = group_info,
  design = ~ group  # group 为分组列名(case/control)
)

# 2. 差异分析(标准化+统计检验)
dds <- DESeq(dds)
# 提取差异结果(case vs control)
res <- results(dds, contrast = c("group", "case", "control"))

# 3. 结果筛选(padj < 0.05 且 |log2FC| > 1)
res_filtered <- res %>% 
  as.data.frame() %>% 
  rownames_to_column("gene_id") %>% 
  filter(padj < 0.05 & abs(log2FoldChange) > 1) %>% 
  arrange(padj)

# 4. 保存差异结果
write.csv(res_filtered, "./differential/lncRNA_diff_expr.csv", row.names = FALSE)

# 5. 可视化:火山图
res_df <- res %>% as.data.frame() %>% rownames_to_column("gene_id")
ggplot(res_df, aes(x = log2FoldChange, y = -log10(padj))) +
  geom_point(aes(color = ifelse(padj < 0.05 & abs(log2FoldChange) > 1, "显著差异", "无差异")),
             alpha = 0.6, size = 1) +
  scale_color_manual(values = c("red", "gray")) +
  labs(x = "log2(Fold Change)", y = "-log10(Adjusted P-value)", color = "差异类型") +
  theme_bw() +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "black") +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black")

ggsave("./plots/lncRNA_volcano.png", width = 8, height = 6, dpi = 300)

# 6. 可视化:热图(top 50 差异 lncRNA)
top50_lncRNA <- res_filtered %>% slice_head(n = 50) %>% pull(gene_id)
top50_counts <- assay(rlog(dds))[top50_lncRNA, ]  # rlog 标准化,降低异方差影响
pheatmap(top50_counts, 
         annotation_col = group_info, 
         show_rownames = FALSE, 
         scale = "row",  # 行标准化(便于比较基因表达模式)
         color = colorRampPalette(c("blue", "white", "red"))(100),
         main = "Top 50 差异 lncRNA 表达热图")

ggsave("./plots/lncRNA_heatmap.png", width = 10, height = 8, dpi = 300)

3. miRNA 差异分析(limma 示例)

miRNA 表达数据常为 TPM 格式,适合用 limma 进行差异分析

R 复制代码
# 1. 读取 miRNA 表达矩阵(TPM 格式)
miRNA_tpm <- read.delim("./quantification/miRNA_tpm.txt", row.names = 1)
miRNA_tpm <- miRNA_tpm[, rownames(group_info)]  # 匹配样本顺序

# 2. 数据转换(TPM 取对数,使分布更接近正态)
miRNA_log <- log2(miRNA_tpm + 1)  # +1 避免 log(0)

# 3. 构建 limma 设计矩阵
design <- model.matrix(~ 0 + group, data = group_info)
colnames(design) <- gsub("group", "", colnames(design))
contrast.matrix <- makeContrasts(case - control, levels = design)

# 4. 差异分析
fit <- lmFit(miRNA_log, design)
fit2 <- contrasts.fit(fit, contrast.matrix)
fit2 <- eBayes(fit2)  # 经验贝叶斯调整
res_miRNA <- topTable(fit2, coef = 1, number = Inf, adjust = "fdr")

# 5. 筛选差异 miRNA(padj < 0.05 且 |log2FC| > 1)
res_miRNA_filtered <- res_miRNA %>% 
  rownames_to_column("miRNA_id") %>% 
  filter(adj.P.Val < 0.05 & abs(logFC) > 1)

# 保存结果
write.csv(res_miRNA_filtered, "./differential/miRNA_diff_expr.csv", row.names = FALSE)

关键说明

  • 差异筛选阈值可根据研究需求调整(如严格筛选用 padj <0.01、|log2FC|> 2)。
  • 若样本量小(n < 3),建议用 edgeR 替代 DESeq2,抗噪声能力更强。

五、第四步:ceRNA 网络构建

ceRNA 网络构建的核心是 "筛选差异分子间的 miRNA 介导的调控关系",需经历 "靶标预测→相互作用筛选→网络构建" 三个步骤。

1. 靶标预测(miRNA 与 ceRNA/mRNA 结合位点预测)

使用 TargetScan(动物 miRNA 靶标预测工具)结合 Python 脚本批量预测。

python 复制代码
import pandas as pd
from targetscan import TargetScan  # 需提前安装:pip install targetscan

# 1. 读取差异分子列表
diff_lncRNA <- pd.read_csv("./differential/lncRNA_diff_expr.csv")["gene_id"].tolist()
diff_circRNA <- pd.read_csv("./differential/circRNA_diff_expr.csv")["circRNA_ID"].tolist()
diff_mRNA <- pd.read_csv("./differential/mRNA_diff_expr.csv")["gene_id"].tolist()
diff_miRNA <- pd.read_csv("./differential/miRNA_diff_expr.csv")["miRNA_id"].tolist()

# 2. 批量预测 miRNA 与 mRNA 的结合位点(TargetScan)
ts = TargetScan()
mirna_mrna_pairs = []

for mirna in diff_miRNA:
    # 预测该 miRNA 的所有靶标 mRNA
    targets = ts.predict(mirna)
    # 筛选出差异 mRNA 中的靶标
    target_mrna = targets[targets["gene_id"].isin(diff_mRNA)]
    if not target_mrna.empty:
        target_mrna["miRNA_id"] = mirna
        mirna_mrna_pairs.append(target_mrna[["miRNA_id", "gene_id", "context_score"]])

# 合并结果(context_score 越小,结合亲和力越强)
mirna_mrna_df = pd.concat(mirna_mrna_pairs, ignore_index = True)
mirna_mrna_df = mirna_mrna_df[mirna_mrna_df["context_score"] < -0.3]  # 筛选高亲和力结合对

# 3. 预测 miRNA 与 lncRNA/circRNA 的结合位点(RNAhybrid)
# RNAhybrid 命令行调用示例(需提前安装 RNAhybrid)
def predict_mirna_ceRNA(mirna, ceRNA_list, ceRNA_type="lncRNA"):
    ceRNA_mirna_pairs = []
    for ceRNA in ceRNA_list:
        # 假设已获取 ceRNA 的序列(需从参考基因组中提取,此处省略序列提取步骤)
        ceRNA_seq = get_ceRNA_sequence(ceRNA)  # 自定义函数:根据 ID 提取序列
        # 调用 RNAhybrid 预测结合自由能(ΔG < -20 kcal/mol 为高亲和力)
        result = os.popen(f"echo -e '{mirna_seq}\\n{ceRNA_seq}' | RNAhybrid -s 2 -m 80 -v 3").read()
        # 解析结果,提取结合自由能
        delta_g = parse_rnahybrid_result(result)  # 自定义函数:解析 RNAhybrid 输出
        if delta_g < -20:
            ceRNA_mirna_pairs.append({"miRNA_id": mirna, "ceRNA_id": ceRNA, "delta_g": delta_g, "ceRNA_type": ceRNA_type})
    return ceRNA_mirna_pairs

# 4. 合并所有相互作用对(miRNA-ceRNA + miRNA-mRNA)
ceRNA_mirna_df = pd.DataFrame(predict_mirna_ceRNA(diff_miRNA, diff_lncRNA, "lncRNA"))
circRNA_mirna_df = pd.DataFrame(predict_mirna_ceRNA(diff_miRNA, diff_circRNA, "circRNA"))
all_interactions = pd.concat([ceRNA_mirna_df, circRNA_mirna_df, mirna_mrna_df], ignore_index = True)

# 保存相互作用列表
all_interactions.to_csv("./ceRNA/miRNA_interactions.csv", index = False)

2. ceRNA 网络构建与可视化

基于相互作用对,用 igraph 构建网络,Cytoscape 可视化核心节点。

R 复制代码
library(igraph)
library(tidyverse)

# 1. 读取相互作用数据
interactions <- read.csv("./ceRNA/miRNA_interactions.csv")

# 2. 构建网络节点数据框(包含节点 ID 和类型)
nodes_lncRNA <- data.frame(
  id = unique(interactions$ceRNA_id[interactions$ceRNA_type == "lncRNA"]),
  type = "lncRNA"
)
nodes_circRNA <- data.frame(
  id = unique(interactions$ceRNA_id[interactions$ceRNA_type == "circRNA"]),
  type = "circRNA"
)
nodes_miRNA <- data.frame(
  id = unique(interactions$miRNA_id),
  type = "miRNA"
)
nodes_mRNA <- data.frame(
  id = unique(interactions$gene_id),
  type = "mRNA"
)
all_nodes <- rbind(nodes_lncRNA, nodes_circRNA, nodes_miRNA, nodes_mRNA)

# 3. 构建网络边数据框(相互作用关系)
edges <- interactions %>% 
  mutate(
    from = ifelse(!is.na(ceRNA_id), ceRNA_id, miRNA_id),
    to = ifelse(!is.na(gene_id), gene_id, miRNA_id)
  ) %>% 
  select(from, to, type = ceRNA_type)

# 4. 用 igraph 构建网络
g <- graph_from_data_frame(d = edges, vertices = all_nodes, directed = FALSE)

# 5. 网络拓扑分析(筛选核心节点)
# 计算节点度(连接的节点数,度越高越核心)
node_degree <- degree(g)
core_nodes <- names(node_degree)[node_degree >= 5]  # 筛选度≥5 的核心节点

# 6. 提取核心网络(仅包含核心节点及相互作用)
core_g <- induced_subgraph(g, vids = core_nodes)

# 7. 保存网络为 Cytoscape 兼容格式(CSV)
write.csv(as_data_frame(core_g, what = "vertices"), "./ceRNA/core_nodes.csv", row.names = FALSE)
write.csv(as_data_frame(core_g, what = "edges"), "./ceRNA/core_edges.csv", row.names = FALSE)

# 8. R 可视化核心网络
V(core_g)$color <- case_when(
  V(core_g)$type == "lncRNA" ~ "red",
  V(core_g)$type == "circRNA" ~ "blue",
  V(core_g)$type == "miRNA" ~ "green",
  V(core_g)$type == "mRNA" ~ "orange"
)
plot(core_g, 
     vertex.size = 5,
     vertex.label.cex = 0.6,
     edge.width = 1,
     layout = layout_with_fr,  # 力导向布局
     main = "ceRNA 核心调控网络")

Cytoscape 可视化步骤

  1. 打开 Cytoscape,导入 core_nodes.csvcore_edges.csv
  2. 在 "Style" 面板设置节点颜色(按类型区分)、大小(按度排序)。
  3. 用 "Layout"→"Force-directed" 优化网络布局,导出高分辨率图片。

六、第五步:功能富集分析

功能富集分析用于解释 ceRNA 网络的生物学意义,核心是分析差异 mRNA 或网络中的 mRNA 富集的 GO 术语(生物过程、细胞组分、分子功能)和 KEGG 通路。

1. GO/KEGG 富集分析(clusterProfiler 示例)

R 复制代码
library(clusterProfiler)
library(org.Hs.eg.db)  # 人类基因注释库(小鼠用 org.Mm.eg.db)
library(ggplot2)

# 1. 读取差异 mRNA 列表(需转换为 Entrez ID 或 Symbol)
diff_mrna <- read.csv("./differential/mRNA_diff_expr.csv")["gene_id"]  # 假设 gene_id 为 Ensembl ID

# 2. 转换 Ensembl ID 为 Entrez ID(富集分析需 Entrez ID)
mrna_entrez <- bitr(
  diff_mrna$gene_id,
  fromType = "ENSEMBL",
  toType = "ENTREZID",
  OrgDb = org.Hs.eg.db
)

# 3. GO 富集分析
go_enrich <- enrichGO(
  gene = mrna_entrez$ENTREZID,
  OrgDb = org.Hs.eg.db,
  keyType = "ENTREZID",
  ont = "BP",  # BP:生物过程(可选 MF/CC)
  pAdjustMethod = "fdr",
  qvalueCutoff = 0.05
)

# 可视化:GO 富集气泡图
dotplot(go_enrich, showCategory = 15, title = "差异 mRNA GO 富集分析(BP)") +
  theme(axis.text.y = element_text(size = 10))
ggsave("./enrichment/GO_BP_dotplot.png", width = 12, height = 8, dpi = 300)

# 4. KEGG 富集分析
kegg_enrich <- enrichKEGG(
  gene = mrna_entrez$ENTREZID,
  organism = "hsa",  # 人类:hsa,小鼠:mmu
  pvalueCutoff = 0.05,
  qvalueCutoff = 0.1
)

# 可视化:KEGG 富集气泡图
dotplot(kegg_enrich, showCategory = 15, title = "差异 mRNA KEGG 富集分析") +
  theme(axis.text.y = element_text(size = 10))
ggsave("./enrichment/KEGG_dotplot.png", width = 12, height = 8, dpi = 300)

# 5. 保存富集结果
write.csv(as.data.frame(go_enrich), "./enrichment/GO_enrichment.csv", row.names = FALSE)
write.csv(as.data.frame(kegg_enrich), "./enrichment/KEGG_enrichment.csv", row.names = FALSE)

2. GSEA 分析(基因集富集分析)

适用于探索差异表达不显著但功能相关的基因集,补充 GO/KEGG 分析的局限性。

R 复制代码
# 1. 准备 GSEA 输入数据(基因表达量排序文件)
# 读取 mRNA 表达矩阵(TPM 格式)
mrna_tpm <- read.delim("./quantification/mRNA_tpm.txt", row.names = 1)
# 计算病例组 vs 对照组的平均表达量比值(log2FC)
case_samples <- rownames(group_info)[group_info$group == "case"]
control_samples <- rownames(group_info)[group_info$group == "control"]
mrna_log2fc <- log2(rowMeans(mrna_tpm[, case_samples]) / rowMeans(mrna_tpm[, control_samples]) + 1)

# 构建排序文件(基因名 + log2FC)
gsea_rnk <- data.frame(
  gene = names(mrna_log2fc),
  log2fc = mrna_log2fc
) %>% 
  arrange(desc(log2fc)) %>% 
  select(gene, log2fc)

# 保存排序文件
write.table(gsea_rnk, "./enrichment/GSEA_rnk.rnk", sep = "\t", quote = FALSE, row.names = FALSE)

# 2. 运行 GSEA(需下载 GSEA 软件,手动运行或调用 R 接口)
# 此处为 GSEA 软件操作步骤:
# 1. 打开 GSEA,导入 rnk 文件和表型文件(分组信息)
# 2. 选择基因集(如 c2.cp.kegg.v7.5.1.symbols.gmt)
# 3. 运行 GSEA,查看富集结果(FDR < 0.25 为显著富集)

# 3. 可视化 GSEA 结果(核心通路富集图)
gsea_result <- read.delim("./enrichment/GSEA_results.txt")  # GSEA 输出结果
gseaplot2(go_enrich, geneSetID = 1, title = gsea_result$Description[1])  # 绘制 top1 通路
ggsave("./enrichment/GSEA_plot.png", width = 10, height = 6, dpi = 300)

七、第六步:实验功能验证

生信分析结果需通过湿实验验证,核心验证方向包括 "分子表达验证→调控关系验证→功能表型验证",以下为关键实验设计与步骤。

1. 分子表达验证(qPCR)

验证生信筛选的差异 lncRNA/circRNA/mRNA/miRNA 在临床样本或细胞系中的表达趋势。

  • 实验材料:临床样本(病例组 vs 对照组,n ≥ 30)、细胞系(如 A549 肺癌细胞)。
  • 关键步骤
    1. 提取总 RNA(Trizol 法),检测 RNA 纯度(A260/A280 = 1.8-2.0)。
    2. 反转录:lncRNA/mRNA 用 oligo (dT) 引物,circRNA/miRNA 用特异性引物。
    3. qPCR 扩增:用 SYBR Green 试剂盒,设置内参基因(GAPDH 用于 mRNA/lncRNA,U6 用于 miRNA)。
    4. 结果分析:用 2^(-ΔΔCt) 法计算相对表达量,t 检验验证组间差异。
  • 验证标准:qPCR 结果与生信分析的表达趋势一致(如生信显示高表达,qPCR 也需验证高表达)。

2. 调控关系验证(双荧光素酶报告基因实验)

验证 ceRNA 与 miRNA、miRNA 与 mRNA 的直接结合关系。

  • 实验设计
    1. 构建野生型(WT)报告载体:将 ceRNA/mRNA 中 miRNA 结合位点的序列克隆到 pmirGLO 载体的 3' UTR 区。
    2. 构建突变型(MUT)报告载体:突变结合位点的核心碱基(如种子区)。
    3. 共转染:将 WT/MUT 载体与 miRNA mimics/NC(阴性对照)共转染 293T 细胞。
  • 结果判断:若 miRNA mimics 转染后,WT 载体的荧光素酶活性显著降低(≥30%),而 MUT 载体无显著变化,证明直接结合。

3. 功能表型验证(细胞实验)

验证核心 ceRNA(lncRNA/circRNA)对细胞增殖、迁移、侵袭等表型的影响。

  • 实验步骤
    1. 细胞转染:用 siRNA 沉默 lncRNA/circRNA,或用过表达载体上调其表达。
    2. 功能实验:
      • 增殖能力:CCK-8 assay、EdU 染色。
      • 迁移 / 侵袭能力:Transwell assay、划痕愈合实验。
      • 凋亡能力:流式细胞术(Annexin V/PI 染色)。
  • 验证逻辑:若沉默核心 ceRNA 后,细胞增殖 / 迁移能力显著降低,且其靶标 miRNA 表达升高、下游 mRNA 表达降低,则验证 ceRNA 网络的调控功能。

八、常见问题与解决方案

  1. 数据比对率低:检查参考基因组版本是否匹配(如人类用 hg38 而非 hg19),或测序数据存在批次效应,需用 sva 包校正。
  2. 差异分子过少:降低筛选阈值(如 padj <0.1、|log2FC|> 0.8),或增加样本量,避免假阴性。
  3. ceRNA 网络假阳性高:仅保留 "高亲和力结合对"(如 RNAhybrid ΔG < -25 kcal/mol),结合共表达分析(ceRNA 与 mRNA 表达正相关)。
  4. 富集结果无显著通路:扩大差异 mRNA 筛选范围,或使用 GSEA 分析替代 GO/KEGG,探索潜在功能关联。

九、总结

非编码 RNA 分析是一个 "从数据到功能" 的系统工程,核心流程可概括为:数据下载与质控→预处理定量→差异筛选→网络构建→功能富集→实验验证。生信分析阶段需注重数据质量控制和工具选择,避免因参数不当导致结果偏差;实验验证阶段需聚焦核心分子和调控关系,确保生信预测的可靠性。

本文提供的代码模板可直接适配人类 / 小鼠的 RNA-seq 数据,研究者可根据自身研究对象(如肿瘤、代谢疾病)调整筛选阈值和实验方案。记住:ncRNA 研究的核心是 "功能机制",生信分析是发现候选分子的工具,最终需通过实验验证揭示其在生物过程中的作用。

相关推荐
许泽宇的技术分享2 小时前
当AI学会“说人话“:Azure语音合成技术的魔法世界
后端·python·flask
光泽雨2 小时前
python学习基础
开发语言·数据库·python
裤裤兔3 小时前
python爬取pdf文件并保存至本地
chrome·爬虫·python·pdf·网络爬虫
CesareCheung3 小时前
JMeter 进行 WebSocket 接口压测
python·websocket·jmeter
beijingliushao3 小时前
95-Python爬虫-正则表达式
爬虫·python·正则表达式
百***06013 小时前
python爬虫——爬取全年天气数据并做可视化分析
开发语言·爬虫·python
吃个糖糖3 小时前
pytorch 卷积操作
人工智能·pytorch·python
麦麦麦造3 小时前
比 pip 快 100 倍!更现代的 python 包管理工具,替代 pip、venv、poetry!
后端·python
AndrewHZ4 小时前
【图像处理基石】图像去雾算法入门(2025年版)
图像处理·人工智能·python·算法·transformer·cv·图像去雾