GSEAlens:基因集富集分析的交互式探索平台

Dudali

2026-05-18

1 R包简介

GSEAlens 中的 Lens(透镜)象征着这个包如同一个放大镜,帮助研究者深入探索 GSEA 富集分析中的关键通路。

GSEAlens 提供了一个基于 Web 界面的交互式平台,用于展示通路的介绍和描述,并集成了 AI 辅助的通路富集结果导出功能。通过封装工作流程和标准化输入格式,这个 R 包简化了 GSEA 富集分析的结果查看和探索过程。

1.1 安装说明

# 使用 devtools 安装
if (!requireNamespace("devtools", quietly = TRUE)) {
    install.packages("devtools")
}
devtools::install_github("DDL095/GSEAlens")

2 示例代码

使用airway包作为示例运行,这个R包当中包含两组每组4个重复

library(GSEAlens)
# 先检查是否已安装 airway
if (!requireNamespace("airway", quietly = TRUE)) {
  # 如果未安装,先检查并安装 BiocManager
  if (!requireNamespace("BiocManager", quietly = TRUE)) {
    install.packages("BiocManager")
  }
  # 通过 BiocManager 安装 airway
  BiocManager::install("airway")
}
library("airway")
data(airway)
expression_data <- airway

2.1 输入数据准备

2.1.1 limma-voom 流程

首先参考标准流程,使用 edgeR 包组装 DGEList 对象,设计无截距矩阵并重命名行名, 之后制作用于拟合的比对,过滤低表达基因,保留蛋白质编码 RNA,使用 symbol 作为行名。

注意:GSEAlens 基于无截距设计的 limma-voom 流程 (~0+group),以确保列名直接对应组别名称。

library(edgeR)
library(limma)
group_level <- airway@colData@listData[["dex"]] 
design <- model.matrix(~0+group_level)
colnames(design) <- levels(group_level)
compare_end <- combn(levels(group_level), 2, simplify = FALSE)
contrast_strings <- sapply(compare_end, function(x) paste(x[2], x[1], sep = " - ")) 
contrast_matrix <- makeContrasts(contrasts = contrast_strings, levels = design)

genes_df <- data.frame(
  gene_id = airway@rowRanges@elementMetadata@listData$gene_id,
  symbol = airway@rowRanges@elementMetadata@listData$symbol,
  gene_biotype = airway@rowRanges@elementMetadata@listData$gene_biotype
)
genes_df$Length <- airway@rowRanges@elementMetadata@listData$gene_seq_end - 
                   airway@rowRanges@elementMetadata@listData$gene_seq_start + 1
gsea_limma_voom_data <- edgeR::DGEList(
  counts = assay(airway, "counts"),
  genes = genes_df,
  norm.factors = NULL,
  group = group_level,
  remove.zeros = T
)
## Removing 30208 rows with all zero counts
total_counts <- edgeR::cpm(gsea_limma_voom_data) |> rowSums()  

dup_symbols <- gsea_limma_voom_data$genes$symbol[duplicated(gsea_limma_voom_data$genes$symbol)]

keep <- rep(TRUE, nrow(gsea_limma_voom_data))

for (gene in dup_symbols) {
  idx <- which(gsea_limma_voom_data$genes$symbol == gene)  
  best_idx <- idx[which.max(total_counts[idx])]            
  remove_idx <- idx[idx != best_idx]                       
  keep[remove_idx] <- FALSE
}

gsea_limma_voom_data <- gsea_limma_voom_data[keep, ]

rownames(gsea_limma_voom_data) <- gsea_limma_voom_data$genes$symbol

keep_biotype <- gsea_limma_voom_data$genes$gene_biotype == "protein_coding"
gsea_limma_voom_data <- gsea_limma_voom_data[keep_biotype,]

gsea_limma_voom_data <- edgeR::normLibSizes(gsea_limma_voom_data, method = "TMM")

isexpr <- rowSums(edgeR::cpm(gsea_limma_voom_data) > 1) >= 3
gsea_limma_voom_data <- gsea_limma_voom_data[isexpr,]

之后进行limma-voom拟合,获取fit对象

VoomOutPut <- voom(gsea_limma_voom_data, design)

fit <- lmFit(object = VoomOutPut, design = design) %>% 
  contrasts.fit(fit = ., contrasts = contrast_matrix) %>% 
  eBayes(.)

2.1.2 DESeq2流程

2.1.2.1 SummarizedExperiment input

参考DESeq2包的说明文档,进行数据清洗与处理。 首先去除非编码RNA

library("DESeq2")
dds_se <- DESeqDataSet(expression_data, design = ~ cell + dex)
gene_biotypes <- rowData(dds_se)$gene_biotype
keep_protein_coding <- gene_biotypes == "protein_coding"
dds_se <- dds_se[keep_protein_coding, ]
dds_se
## class: DESeqDataSet 
## dim: 22810 8 
## metadata(2): '' version
## assays(1): counts
## rownames(22810): ENSG00000000003 ENSG00000000005 ... ENSG00000273482
##   ENSG00000273490
## rowData names(10): gene_id gene_name ... seq_coord_system symbol
## colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
## colData names(9): SampleName cell ... Sample BioSample

之后去除低表达基因,使用symbol作为行名

smallestGroupSize <- 3
keep <- rowSums(counts(dds_se) >= 10) >= smallestGroupSize
dds_se <- dds_se[keep,]
dds_se
## class: DESeqDataSet 
## dim: 13256 8 
## metadata(2): '' version
## assays(1): counts
## rownames(13256): ENSG00000000003 ENSG00000000419 ... ENSG00000272047
##   ENSG00000272325
## rowData names(10): gene_id gene_name ... seq_coord_system symbol
## colnames(8): SRR1039508 SRR1039509 ... SRR1039520 SRR1039521
## colData names(9): SampleName cell ... Sample BioSample
rownames(dds_se) <- dds_se@rowRanges@elementMetadata@listData[["gene_name"]]

total_counts <- rowSums(SummarizedExperiment::assay(dds_se))
keep <- rep(TRUE, nrow(dds_se))
dup_genes <- rownames(dds_se)[duplicated(rownames(dds_se))]
for (gene in dup_genes) {
  idx <- which(rownames(dds_se) == gene)  
  best_idx <- idx[which.max(total_counts[idx])]  
  remove_idx <- idx[idx != best_idx]  
  keep[remove_idx] <- FALSE
}
dds_se <- dds_se[keep, ]

运行DESeq2处理

dds_se <- DESeq(dds_se)
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing

2.1.3 Count matrix input

过滤低表达基因,保留仅蛋白质编码RNA,并将矩阵行名修订为symbol

DDS_rawdata <- expression_data

gene_biotypes_epd <- rowData(DDS_rawdata)$gene_biotype
keep_protein_coding_epd <- gene_biotypes == "protein_coding"
DDS_rawdata <- DDS_rawdata[keep_protein_coding, ]

smallestGroupSize <- 3
keep_epd <- rowSums(assay(DDS_rawdata, "counts") >= 10) >= smallestGroupSize
DDS_rawdata <- DDS_rawdata[keep_epd,]

rownames(DDS_rawdata) <- DDS_rawdata@rowRanges@elementMetadata@listData[["gene_name"]]

total_counts <- rowSums(SummarizedExperiment::assay(DDS_rawdata))
keep_name <- rep(TRUE, nrow(DDS_rawdata))
dup_genes <- rownames(DDS_rawdata)[duplicated(rownames(DDS_rawdata))]
for (gene in dup_genes) {
  idx <- which(rownames(DDS_rawdata) == gene)  # 该基因的所有行索引
  best_idx <- idx[which.max(total_counts[idx])]  # 表达量最高的行
  remove_idx <- idx[idx != best_idx]  # 要剔除的行(同一基因名下非最高表达)
  keep_name[remove_idx] <- FALSE
}
DDS_rawdata <- DDS_rawdata[keep_name, ]

矩阵信息获取

cts <- assay(DDS_rawdata,"counts")
coldata <- DDS_rawdata@colData %>% as.data.frame.array()
coldata <- coldata[,c("cell","dex")]
coldata$cell <- factor(coldata$cell)
coldata$dex <- factor(coldata$dex)

组装为DDS对象并进行处理

dds <- DESeqDataSetFromMatrix(countData = cts,
                              colData = coldata,
                              design = ~ dex)
dds <- DESeq(dds)
## estimating size factors
## estimating dispersions
## gene-wise dispersion estimates
## mean-dispersion relationship
## final dispersion estimates
## fitting model and testing

2.2 GSEAlens处理

2.2.1 创建GSEA基因集对象

使用build_gsea_pathways函数构建用于GSEA富集分析的基因集对象

gsea_pathwaysets <- GSEAlens::build_gsea_pathways(species = "HS",auto_select = c(17,18,19,20,26))
## [build_gsea_pathways] Species: Homo sapiens (Human)
## 
## Selected 5 collection(s). Batch Tag: [Mix5_HS_C5_GO_BP]
## 
## [build_gsea_pathways] Done! Built 16333 pathways x 19676 genes for Homo sapiens (Human)

2.2.2 组装运算对象

通过setup_gsea_env函数,组装用于计算分析的GSEAEnv对象,不同的终端使用同一个函数,仅纳入数据不同,对于limma-voom流程,由于fit对象当中不包含原始的基因读数,因此必须额外纳入过滤后用于生成fit对象的DGEList,本例中为多步过滤的gsea_limma_voom_data

limma-voom 流程对象纳入分析。

gseadata_limmavoom <- GSEAlens::setup_gsea_env(fit = fit,pathway_obj = gsea_pathwaysets,expr_data = gsea_limma_voom_data)
## 
## Starting GSEAlens engine...
## Detected input type: [Limma-Voom]
## GseaEnv object built successfully!
##    Contains 1 contrast groups
##    Contains 16333 pathways

DESeq2 的 SummarizedExperiment 对象纳入分析。

gseadata_se <- GSEAlens::setup_gsea_env(fit = dds_se,pathway_obj = gsea_pathwaysets)
## 
## Starting GSEAlens engine...
## Detected input type: [DESeq2]
## [DESeq2] target_factor not specified, automatically inferred as: 'dex'
## GseaEnv object built successfully!
##    Contains 1 contrast groups
##    Contains 16333 pathways

DESeq2 的 Count matrix 流程的对象纳入分析。

gseadata_dds <- GSEAlens::setup_gsea_env(fit = dds,pathway_obj = gsea_pathwaysets)
## 
## Starting GSEAlens engine...
## Detected input type: [DESeq2]
## [DESeq2] target_factor not specified, automatically inferred as: 'dex'
## GseaEnv object built successfully!
##    Contains 1 contrast groups
##    Contains 16333 pathways

2.2.3 运行处理

所有对象均使用batch_calc_gsea这个函数处理,没有任何区别。

并行计算提示:可根据电脑性能调整 workers 选项,设置计算使用的核心数量。 比对数量越多,建议设置越高的核心数以提升计算效率。

# limma-voom 流程
gsea_res_limmavoom <- GSEAlens::batch_calc_gsea(gseadata_limmavoom, 
                                                 custom_series_name = "limmavoom_data", 
                                                 workers = 4,  # 根据比对数量和电脑性能调整
                                                 force = TRUE)

# DESeq2 SummarizedExperiment 流程
gsea_res_se <- GSEAlens::batch_calc_gsea(gseadata_se, 
                                          custom_series_name = "dds_se_data", 
                                          workers = 4,
                                          force = TRUE)

# DESeq2 Count matrix 流程
gsea_res_dds <- GSEAlens::batch_calc_gsea(gseadata_dds, 
                                           custom_series_name = "dds_data", 
                                           workers = 4,
                                           force = TRUE)

2.2.4 交互式分析与查看

运行batch_calc_gsea之后,在对应目录下会生成一个RDS文件,读入该文件,或者使用import_gsea_capsule读取,import_gsea_capsule函数可以在读取的时候,自动将相关文件整理到使用的RMD文件或者R脚本的文件夹中,并且给出数据的检视情况。

gsea_res <- import_gsea_capsule("/path/to/your/files/")
# 或直接读取 RDS 文件
# gsea_res <- readRDS("/path/of/your/file/")

数据载入后,就可以使用launch_gsea_app进行交互式查看

launch_gsea_app(gsea_res)

3 R包中间对象说明

3.1 GseaEnv 对象

setup_gsea_env 函数返回的 GseaEnv 对象包含以下组件: | 组件 | 说明 | |——|——| | backend_info | 后端类型信息(limma-voom 或 DESeq2) | | contrast_registry | 对比组注册表,包含所有成对比较信息 | | de_store | 差异分析结果存储 | | expr_bundle | 表达数据封装(原始计数、标准化矩阵、样本元数据) | | geneset | 基因集信息(TERM2GENE、元数据字典、物种) |

3.2 GseaRes 对象

batch_calc_gsea 函数返回的 GseaRes 对象包含以下组件: | 组件 | 说明 | |——|——| | metadata | 计算元数据(运行时间、使用的核心数、参数设置) | | backend_info | 后端类型信息 | | contrast_registry | 对比组注册表 | | de_store | 差异分析结果存储 | | expr_bundle | 表达数据封装 | | geneset_info | 基因集信息 | | results | GSEA 结果列表,每个对比组对应一个条目 |

3.3 GseaTask 对象

extract_gsea_task 函数返回的 GseaTask 对象用于单对比分析:

组件 说明
gsea_res GSEA result 对象
meta 元信息(对比组信息、基因集名称、表达数据)

4 Session info

sessionInfo()
## R version 4.6.0 RC (2026-04-17 r89917)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.4 LTS
## 
## Matrix products: default
## BLAS:   /home/biocbuild/bbs-3.23-bioc/R/lib/libRblas.so 
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_GB              LC_COLLATE=C              
##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: America/New_York
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats4    stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
##  [1] DESeq2_1.52.0               edgeR_4.10.0               
##  [3] limma_3.68.2                airway_1.32.0              
##  [5] SummarizedExperiment_1.42.0 Biobase_2.72.0             
##  [7] GenomicRanges_1.64.0        Seqinfo_1.2.0              
##  [9] IRanges_2.46.0              S4Vectors_0.50.1           
## [11] BiocGenerics_0.58.1         generics_0.1.4             
## [13] MatrixGenerics_1.24.0       matrixStats_1.5.0          
## [15] GSEAlens_0.99.0            
## 
## loaded via a namespace (and not attached):
##   [1] splines_4.6.0           later_1.4.8             ggplotify_0.1.3        
##   [4] tibble_3.3.1            polyclip_1.10-7         enrichit_0.1.4         
##   [7] lifecycle_1.0.5         httr2_1.2.2             doParallel_1.0.17      
##  [10] globals_0.19.1          processx_3.9.0          lattice_0.22-9         
##  [13] MASS_7.3-65             magrittr_2.0.5          plotly_4.12.0          
##  [16] sass_0.4.10             rmarkdown_2.31          jquerylib_0.1.4        
##  [19] yaml_2.3.12             httpuv_1.6.17           otel_0.2.0             
##  [22] ggtangle_0.1.2          DBI_1.3.0               RColorBrewer_1.1-3     
##  [25] abind_1.4-8             purrr_1.2.2             msigdbr_26.1.0         
##  [28] yulab.utils_0.2.4       tweenr_2.0.3            rappdirs_0.3.4         
##  [31] aisdk_1.1.0             gdtools_0.5.0           circlize_0.4.18        
##  [34] enrichplot_1.32.0       ggrepel_0.9.8           listenv_0.10.1         
##  [37] tidytree_0.4.7          parallelly_1.47.0       codetools_0.2-20       
##  [40] DelayedArray_0.38.1     DOSE_4.6.0              DT_0.34.0              
##  [43] ggforce_0.5.0           tidyselect_1.2.1        shape_1.4.6.1          
##  [46] aplot_0.2.9             farver_2.1.2            jsonlite_2.0.0         
##  [49] GetoptLong_1.1.1        iterators_1.0.14        systemfonts_1.3.2      
##  [52] foreach_1.5.2           tools_4.6.0             ggnewscale_0.5.2       
##  [55] treeio_1.36.1           Rcpp_1.1.1-1.1          glue_1.8.1             
##  [58] SparseArray_1.12.2      xfun_0.57               qvalue_2.44.0          
##  [61] dplyr_1.2.1             withr_3.0.2             fastmap_1.2.0          
##  [64] callr_3.7.6             digest_0.6.39           R6_2.6.1               
##  [67] mime_0.13               gridGraphics_0.5-1      colorspace_2.1-2       
##  [70] GO.db_3.23.1            dichromat_2.0-0.1       RSQLite_3.52.0         
##  [73] tidyr_1.3.2             fontLiberation_0.1.0    data.table_1.18.4      
##  [76] httr_1.4.8              htmlwidgets_1.6.4       S4Arrays_1.12.0        
##  [79] scatterpie_0.2.6        pkgconfig_2.0.3         gtable_0.3.6           
##  [82] blob_1.3.0              ComplexHeatmap_2.28.0   S7_0.2.2               
##  [85] XVector_0.52.0          clusterProfiler_4.20.0  htmltools_0.5.9        
##  [88] fontBitstreamVera_0.1.1 clue_0.3-68             scales_1.4.0           
##  [91] png_0.1-9               ggfun_0.2.0             knitr_1.51             
##  [94] reshape2_1.4.5          rjson_0.2.23            nlme_3.1-169           
##  [97] curl_7.1.0              cachem_1.1.0            GlobalOptions_0.1.4    
## [100] stringr_1.6.0           shinycssloaders_1.1.0   parallel_4.6.0         
## [103] AnnotationDbi_1.74.0    pillar_1.11.1           grid_4.6.0             
## [106] vctrs_0.7.3             promises_1.5.0          tidydr_0.0.6           
## [109] xtable_1.8-8            cluster_2.1.8.2         evaluate_1.0.5         
## [112] cli_3.6.6               locfit_1.5-9.12         compiler_4.6.0         
## [115] rlang_1.2.0             crayon_1.5.3            future.apply_1.20.2    
## [118] ps_1.9.3                plyr_1.8.9              fs_2.1.0               
## [121] ggiraph_0.9.6           stringi_1.8.7           viridisLite_0.4.3      
## [124] BiocParallel_1.46.0     assertthat_0.2.1        babelgene_22.9         
## [127] Biostrings_2.80.0       lazyeval_0.2.3          GOSemSim_2.38.0        
## [130] fontquiver_0.2.1        Matrix_1.7-5            patchwork_1.3.2        
## [133] bit64_4.8.0             future_1.70.0           ggplot2_4.0.3          
## [136] KEGGREST_1.52.0         statmod_1.5.2           shiny_1.13.0           
## [139] clipr_0.8.0             igraph_2.3.1            memoise_2.0.1          
## [142] bslib_0.11.0            ggtree_4.2.0            bit_4.6.0              
## [145] ape_5.8-1               gson_0.1.0

5 References