########--------GSE98177二代测序数据的分析--------######## # GSE98177数据分析:识别调控IL2RA的增强子 # 1. 加载必要包 -------------------------------------------------------------- library(GEOquery)
## 载入需要的程序包:Biobase
## 载入需要的程序包:BiocGenerics
## ## 载入程序包:'BiocGenerics'
## The following objects are masked from 'package:stats': ## ## IQR, mad, sd, var, xtabs
## The following objects are masked from 'package:base': ## ## anyDuplicated, aperm, append, as.data.frame, basename, cbind, ## colnames, dirname, do.call, duplicated, eval, evalq, Filter, Find, ## get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, ## match, mget, order, paste, pmax, pmax.int, pmin, pmin.int, ## Position, rank, rbind, Reduce, rownames, sapply, setdiff, table, ## tapply, union, unique, unsplit, which.max, which.min
## Welcome to Bioconductor ## ## Vignettes contain introductory material; view with ## 'browseVignettes()'. To cite Bioconductor, see ## 'citation("Biobase")', and for packages 'citation("pkgname")'.
## Setting options('download.file.method.GEOquery'='auto')
## Setting options('GEOquery.inmemory.gpl'=FALSE)
library(DESeq2)
## 载入需要的程序包:S4Vectors
## Warning: 程序包'S4Vectors'是用R版本4.4.1 来建造的
## 载入需要的程序包:stats4
## ## 载入程序包:'S4Vectors'
## The following object is masked from 'package:utils': ## ## findMatches
## The following objects are masked from 'package:base': ## ## expand.grid, I, unname
## 载入需要的程序包:IRanges
## Warning: 程序包'IRanges'是用R版本4.4.1 来建造的
## ## 载入程序包:'IRanges'
## The following object is masked from 'package:grDevices': ## ## windows
## 载入需要的程序包:GenomicRanges
## Warning: 程序包'GenomicRanges'是用R版本4.4.1 来建造的
## 载入需要的程序包:GenomeInfoDb
## 载入需要的程序包:SummarizedExperiment
## 载入需要的程序包:MatrixGenerics
## 载入需要的程序包:matrixStats
## ## 载入程序包:'matrixStats'
## The following objects are masked from 'package:Biobase': ## ## anyMissing, rowMedians
## ## 载入程序包:'MatrixGenerics'
## The following objects are masked from 'package:matrixStats': ## ## colAlls, colAnyNAs, colAnys, colAvgsPerRowSet, colCollapse, ## colCounts, colCummaxs, colCummins, colCumprods, colCumsums, ## colDiffs, colIQRDiffs, colIQRs, colLogSumExps, colMadDiffs, ## colMads, colMaxs, colMeans2, colMedians, colMins, colOrderStats, ## colProds, colQuantiles, colRanges, colRanks, colSdDiffs, colSds, ## colSums2, colTabulates, colVarDiffs, colVars, colWeightedMads, ## colWeightedMeans, colWeightedMedians, colWeightedSds, ## colWeightedVars, rowAlls, rowAnyNAs, rowAnys, rowAvgsPerColSet, ## rowCollapse, rowCounts, rowCummaxs, rowCummins, rowCumprods, ## rowCumsums, rowDiffs, rowIQRDiffs, rowIQRs, rowLogSumExps, ## rowMadDiffs, rowMads, rowMaxs, rowMeans2, rowMedians, rowMins, ## rowOrderStats, rowProds, rowQuantiles, rowRanges, rowRanks, ## rowSdDiffs, rowSds, rowSums2, rowTabulates, rowVarDiffs, rowVars, ## rowWeightedMads, rowWeightedMeans, rowWeightedMedians, ## rowWeightedSds, rowWeightedVars
## The following object is masked from 'package:Biobase': ## ## rowMedians
library(tidyverse)
## Warning: 程序包'tidyverse'是用R版本4.4.2 来建造的
## Warning: 程序包'lubridate'是用R版本4.4.2 来建造的
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ── ## ✔ dplyr 1.1.4 ✔ readr 2.1.5 ## ✔ forcats 1.0.0 ✔ stringr 1.5.1 ## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1 ## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1 ## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ── ## ✖ lubridate::%within%() masks IRanges::%within%() ## ✖ dplyr::collapse() masks IRanges::collapse() ## ✖ dplyr::combine() masks Biobase::combine(), BiocGenerics::combine() ## ✖ dplyr::count() masks matrixStats::count() ## ✖ dplyr::desc() masks IRanges::desc() ## ✖ tidyr::expand() masks S4Vectors::expand() ## ✖ dplyr::filter() masks stats::filter() ## ✖ dplyr::first() masks S4Vectors::first() ## ✖ dplyr::lag() masks stats::lag() ## ✖ ggplot2::Position() masks BiocGenerics::Position(), base::Position() ## ✖ purrr::reduce() masks GenomicRanges::reduce(), IRanges::reduce() ## ✖ dplyr::rename() masks S4Vectors::rename() ## ✖ lubridate::second() masks S4Vectors::second() ## ✖ lubridate::second<-() masks S4Vectors::second<-() ## ✖ dplyr::slice() masks IRanges::slice() ## ℹ Use the conflicted package ( ) to force all conflicts to become errors
library(ggplot2) library(pheatmap) library(clusterProfiler)
## Warning: 程序包'clusterProfiler'是用R版本4.4.1 来建造的
## ## clusterProfiler v4.12.6 Learn more at https://yulab-smu.top/contribution-knowledge-mining/ ## ## Please cite: ## ## T Wu, E Hu, S Xu, M Chen, P Guo, Z Dai, T Feng, L Zhou, W Tang, L Zhan, ## X Fu, S Liu, X Bo, and G Yu. clusterProfiler 4.0: A universal ## enrichment tool for interpreting omics data. The Innovation. 2021, ## 2(3):100141 ## ## 载入程序包:'clusterProfiler' ## ## The following object is masked from 'package:purrr': ## ## simplify ## ## The following object is masked from 'package:IRanges': ## ## slice ## ## The following object is masked from 'package:S4Vectors': ## ## rename ## ## The following object is masked from 'package:stats': ## ## filter
library(org.Hs.eg.db)
## 载入需要的程序包:AnnotationDbi ## ## 载入程序包:'AnnotationDbi' ## ## The following object is masked from 'package:clusterProfiler': ## ## select ## ## The following object is masked from 'package:dplyr': ## ## select
# 2. 数据下载与加载 ---------------------------------------------------------- cat("Step 1: 下载并加载GSE98177数据...\n")
## Step 1: 下载并加载GSE98177数据...
gse <- getGEO("GSE98177", GSEMatrix = TRUE)
## Found 1 file(s) ## GSE98177_series_matrix.txt.gz
# 获取表达矩阵和样本信息 expr_data <- exprs(gse[[1]]) # 标准化表达矩阵(如log2FPKM) pdata <- pData(gse[[1]]) # 样本元数据 count_data <- read.table("GSE98177_raw_counts_tsv.gz", header=TRUE) count_data <- count_data %>% rename(ENTREZID = GeneID) count_data <- count_data %>% mutate(ENTREZID = as.character(ENTREZID)) # 获取所有可能的映射 all_mappings <- select(org.Hs.eg.db, keys = as.character(count_data$ENTREZID), columns = "SYMBOL", keytype = "ENTREZID")
## 'select()' returned 1:1 mapping between keys and columns
# 处理一对多关系 - 选择表达量最高的那个样本的符号 library(dplyr) final_mapping <- count_data %>% left_join(all_mappings, by = "ENTREZID") %>% group_by(ENTREZID) %>% mutate(SYMBOL = ifelse(all(is.na(SYMBOL)), ENTREZID, na.omit(SYMBOL)[1])) %>% # 添加计数使SYMBOL唯一 group_by(SYMBOL) %>% mutate(dup_count = seq_along(SYMBOL), UNIQUE_SYMBOL = ifelse(dup_count > 1, paste0(SYMBOL, "_", dup_count), as.character(SYMBOL))) %>% ungroup() %>% distinct(ENTREZID, .keep_all = TRUE) data = as.data.frame(final_mapping) row.names(data) = data$UNIQUE_SYMBOL # 使用唯一的符号作为行名 # 移除临时列 dat = data[,c(2:19)] # 3. 样本分组设计 ----------------------------------------------------------- cat("Step 2: 设置样本分组...\n")
## Step 2: 设置样本分组...
pdata$condition <- factor(c( rep("NonTargeting", 2), rep("TSS_sg1", 2), rep("TSS_sg2", 2), rep("CaRE3_sg1", 2), rep("CaRE3_sg2", 2), rep("CaRE4_sg1", 2), rep("CaRE4_sg2", 2), rep("PBS", 2), rep("Stimulated", 2) )) pdata$condition <- factor(pdata$condition, levels = c("NonTargeting", "TSS_sg1", "TSS_sg2", "CaRE3_sg1", "CaRE3_sg2", "CaRE4_sg1", "CaRE4_sg2", "PBS", "Stimulated")) # 4. 差异表达分析 ---------------------------------------------------------- cat("Step 3: 进行差异表达分析...\n")
## Step 3: 进行差异表达分析...
# 差异分析 dds <- DESeqDataSetFromMatrix( countData = dat, colData = pdata, design = ~ condition ) # 运行DESeq2 dds <- DESeq(dds)
## estimating size factors ## estimating dispersions ## gene-wise dispersion estimates ## mean-dispersion relationship ## final dispersion estimates ## fitting model and testing
# 比较组分析 res_care3_sg1 <- results(dds, contrast = c("condition", "CaRE3_sg1", "NonTargeting")) res_care3_sg2 <- results(dds, contrast = c("condition", "CaRE3_sg2", "NonTargeting")) res_care4_sg1 <- results(dds, contrast = c("condition", "CaRE4_sg1", "NonTargeting")) # 5. IL2RA表达分析 --------------------------------------------------------- cat("Step 4: 分析IL2RA表达模式...\n")
## Step 4: 分析IL2RA表达模式...
il2ra_id <- "IL2RA" # 假设IL2RA存在于数据中 # 提取归一化表达数据 il2ra_expr <- log2(counts(dds, normalized=TRUE)[il2ra_id, ] + 1) il2ra_df <- data.frame( expr = as.numeric(il2ra_expr), condition = pdata$condition ) # 绘制表达箱线图 ggplot(il2ra_df, aes(x = condition, y = expr, fill = condition)) + geom_boxplot() + geom_jitter(width = 0.2) + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1)) + labs( title = "IL2RA Expression Across Conditions", y = "Normalized Counts (log2)", x = "" )
# 6. 差异基因热图 ---------------------------------------------------------- cat("Step 5: 生成差异基因热图...\n")
## Step 5: 生成差异基因热图...
# 获取显著差异基因(padj < 0.05 & |log2FC| > 1) sig_genes <- rownames(res_care3_sg1)[ which(res_care3_sg1$padj < 0.05 & abs(res_care3_sg1$log2FoldChange) > 1) ] # 确保sig_genes存在于vsd数据中 vsd <- vst(dds, blind=FALSE) sig_genes <- sig_genes[sig_genes %in% rownames(assay(vsd))] # 如果找到显著基因则绘制热图 if(length(sig_genes) > 0){ vsd <- vst(dds, blind=FALSE) mat <- assay(vsd)[sig_genes, , drop=FALSE] # 检查mat是否有有效数据 if(all(is.finite(mat))) { # 对数据进行缩放 mat_scaled <- t(scale(t(mat))) # 设置热图颜色 heatmap_colors <- colorRampPalette(c("blue", "white", "red"))(100) # 只有当基因和样本数都≥2时才绘制聚类热图 if(nrow(mat_scaled) >= 2 && ncol(mat_scaled) >= 2){ pheatmap(mat_scaled, annotation_col = pdata["condition"], show_rownames = ifelse(length(sig_genes) < 50, TRUE, FALSE), scale = "none", color = heatmap_colors, main = "Differentially Expressed Genes in CaRE3 vs Control", cluster_rows = TRUE, cluster_cols = TRUE, fontsize_row = 8, fontsize_col = 8) } elseif (nrow(mat_scaled) >= 1) { # 如果只有1个基因但有足够样本,绘制非聚类热图 cat("注意: 只有", nrow(mat_scaled), "个差异基因 - 绘制简化热图\n") pheatmap(mat_scaled, annotation_col = pdata["condition"], show_rownames = TRUE, scale = "none", color = heatmap_colors, main = paste("Single DEG:", rownames(mat_scaled)), cluster_rows = FALSE, cluster_cols = FALSE, fontsize_row = 8, fontsize_col = 8) } } else { cat("警告: 热图数据包含非有限值(NA/NaN/Inf)\n") problematic_genes <- apply(mat, 1, function(x) any(!is.finite(x))) print(names(which(problematic_genes))) } } else { cat("未检测到满足条件的显著差异基因\n") }
## 注意: 只有 1 个差异基因 - 绘制简化热图
# 7. 功能富集分析 ---------------------------------------------------------- cat("Step 6: 进行功能富集分析...\n")
## Step 6: 进行功能富集分析...
# 示例基因列表(实际应使用差异分析结果) example_genes <- c("IL2RA", "CD28", "CD3D", "CD4", "FOXP3", "STAT5A") # 转换基因ID entrez_ids <- mapIds(org.Hs.eg.db, keys = example_genes, column = "ENTREZID", keytype = "SYMBOL")
## 'select()' returned 1:1 mapping between keys and columns
# GO富集分析 go_enrich <- enrichGO( gene = na.omit(entrez_ids), OrgDb = org.Hs.eg.db, ont = "BP", pAdjustMethod = "BH", readable = TRUE ) # 绘制富集结果 if(nrow(go_enrich) > 0){ dotplot(go_enrich, title = "GO Enrichment Analysis") } else { cat("未检测到显著富集的GO terms\n") }
# 8. 结果汇总 -------------------------------------------------------------- cat("\n===== 分析完成 =====\n")
## ## ===== 分析完成 =====
cat("关键结论检查:\n")
## 关键结论检查:
cat("1. 检查IL2RA在各处理组中的表达变化\n")
## 1. 检查IL2RA在各处理组中的表达变化
cat("2. 验证差异基因是否富集于T细胞激活相关通路\n")
## 2. 验证差异基因是否富集于T细胞激活相关通路
cat("3. 比较CaRE3和CaRE4处理组的差异基因重叠情况\n")
## 3. 比较CaRE3和CaRE4处理组的差异基因重叠情况
cat("Step 4: 分析IL2RA表达模式...\n")
## Step 4: 分析IL2RA表达模式...
cat("Step 5: 生成差异基因热图...\n")
## Step 5: 生成差异基因热图...
cat("Step 6: 进行功能富集分析...\n")
## Step 6: 进行功能富集分析...
热门跟贴