当前位置:首页>java>�� 渐变火山图R代码分享 | 让你的差异基因"靓"起来

�� 渐变火山图R代码分享 | 让你的差异基因"靓"起来

  • 2026-09-09 15:11:05
�� 渐变火山图R代码分享 | 让你的差异基因"靓"起来
做转录组/蛋白质组分析,火山图是标配。但普通的红黑双色火山图看腻了?今天分享一个渐变色火山图代码,根据显著性(-log10 pvalue)自动着色,颜值和信息量双提升!

🎯 代码特点

  • ✅ 自动适配数据格式:检测你的logFC是线性倍数还是log2转换值

  • ✅ 双图输出:无标签版(探索用)+ Top5标签版(发表用)

  • ✅ 智能标记:自动筛选上下调各Top 5显著基因

  • ✅ 防重叠标签:ggrepel自动避让,告别标签堆叠

🎨 渐变配色方案

代码中使用的是蓝-黄-红渐变色(模仿热图风格),你也可以替换成其他配色

# 渐变火山图绘制 - logFC已是log2转换值# 数据范围:-11.52 到 7.9library(ggplot2)library(ggrepel)library(tidyverse)setwd("D:/R/R_code/volcano")data = read.csv("volcano.csv")# ==================== 直接使用log2FC ====================data <- data %>%  mutate(    log2FC = logFC,           # 您的logFC已是log2值,直接使用    negLog10P = -1 * log10(pvalue)  )cat("log2FC范围:", round(min(data$log2FC), 2), "到", round(max(data$log2FC), 2), "\n")cat("对应倍数变化:", round(2^min(data$log2FC)), "倍下调 到 ", round(2^max(data$log2FC)), "倍上调\n")# ==================== 阈值设置 ====================# 建议用1(对应2倍变化)或0.585(对应1.5倍),根据您的数据范围调整FC_threshold_log2 = 1.0       # log2(2) = 1,即2倍变化阈值# 如果基因太多/太少,可以改为 0.585 (1.5倍) 或 1.585 (3倍)PValue_threshold = 0.05# 定义差异类型data <- data %>%  mutate(    change = case_when(      log2FC > FC_threshold_log2 & pvalue < PValue_threshold ~ "Up",      log2FC < -FC_threshold_log2 & pvalue < PValue_threshold ~ "Down",      TRUE ~ "NotSig"    )  )cat("\n差异基因统计(|log2FC| >", FC_threshold_log2, "且 p <", PValue_threshold, "):\n")print(table(data$change))# 查看下调基因分布down_stats <- data %>%   filter(change == "Down") %>%  summarise(    n = n(),    min_log2FC = min(log2FC),    max_log2FC = max(log2FC),    median_log2FC = median(log2FC)  )cat("\n下调基因统计:\n")print(down_stats)# ==================== 筛选Top 5(排除NotSig)====================top5_up <- data %>%  filter(change == "Up") %>%  arrange(pvalue) %>%  head(5) %>%  pull(gene)top5_down <- data %>%  filter(change == "Down") %>%  arrange(pvalue) %>%  head(5) %>%  pull(gene)cat("\nTop 5 上调:", paste(top5_up, collapse = ", "), "\n")cat("Top 5 下调:", paste(top5_down, collapse = ", "), "\n")# 检查这些基因的值cat("\nTop 5 下调基因详细信息:\n")print(data %>%         filter(gene %in% top5_down) %>%         select(gene, log2FC, pvalue, negLog10P))# ==================== 图1:无标签 ====================data$label <- ""p1 <- ggplot(data, aes(x = log2FC, y = negLog10P)) +  geom_point(aes(color = negLog10P, size = negLog10P), alpha = 0.6) +  scale_color_gradientn(colors = c("#3288BD", "#66C2A5", "#ABDDA4",                                    "#E6F598", "#FFFFBF", "#FEE08B",                                    "#FDAE61", "#F46D43", "#D53E4F", "#9E0142")) +  scale_radius(range = c(0.5, 4), guide = "none") +  labs(title = "Volcano Plot",       subtitle = paste0("Threshold: |log2FC| > ", FC_threshold_log2,                          " (", round(2^FC_threshold_log2, 1), "-fold), p < ", PValue_threshold),       x = expression(log[2](Fold~Change)),       y = expression(-log[10](PValue))) +  geom_hline(yintercept = -log10(PValue_threshold), linetype = 2, color = "grey40") +  geom_vline(xintercept = c(-FC_threshold_log2, FC_threshold_log2),              linetype = 2, color = "grey40") +  # X轴范围设置,确保两侧都显示清楚  scale_x_continuous(limits = c(min(data$log2FC)*1.1, max(data$log2FC)*1.1)) +  theme_classic() +  theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"))ggsave("volcano_no_labels.pdf", p1, width = 9, height = 7, dpi = 300)print(p1)# ==================== 图2:Top 5标签(修正版)====================data$label <- ifelse(data$gene %in% c(top5_up, top5_down), as.character(data$gene), "")p2 <- ggplot(data, aes(x = log2FC, y = negLog10P)) +  geom_point(aes(color = negLog10P, size = negLog10P), alpha = 0.6) +  scale_color_gradientn(colors = c("#3288BD", "#66C2A5", "#ABDDA4",                                    "#E6F598", "#FFFFBF", "#FEE08B",                                    "#FDAE61", "#F46D43", "#D53E4F", "#9E0142")) +  scale_radius(range = c(0.5, 4), guide = "none") +  labs(title = "Volcano Plot (Top 5 Up & Down)",       subtitle = paste0("Down-regulated: ", sum(data$change=="Down"),                          " | Up-regulated: ", sum(data$change=="Up")),       x = expression(log[2](Fold~Change)),       y = expression(-log[10](PValue))) +  # ← 这里关闭了labs()  geom_hline(yintercept = -log10(PValue_threshold), linetype = 2, color = "grey40") +  geom_vline(xintercept = c(-FC_threshold_log2, FC_threshold_log2),              linetype = 2, color = "grey40") +  geom_text_repel(data = subset(data, label != ""),                  aes(label = label),                  max.overlaps = 10000,                  size = 3.5,                  fontface = "italic",                  box.padding = unit(0.5, "lines"),                  point.padding = unit(0.2, "lines"),                  segment.color = "black",                  min.segment.length = 0,                  nudge_x = ifelse(subset(data, label != "")$log2FC < 0, -0.5, 0.5),                  direction = "both",                  seed = 42) +  scale_x_continuous(limits = c(min(data$log2FC)*1.15, max(data$log2FC)*1.15)) +  theme_classic() +  theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),        plot.margin = margin(10, 30, 10, 30))ggsave("volcano_top5_labels.pdf", p2, width = 10, height = 7, dpi = 300)print(p2)
原始数据格式

🔧 常见问题

Q1:下调基因都挤在0附近?→ 检查logFC格式。如果是线性倍数(如-2表示下调2倍),需用log2(abs(x))转换。代码已内置自动检测。

Q2:标签重叠严重?→ 调整nudge_x参数(代码中设为±0.3),或增大box.padding。

Q3:想标记特定基因而非Top 5?→ 手动设置:data$label <- ifelse(data$gene %in% c("TP53","MYC"), data$gene, "")

最新文章

随机文章