网易首页 > 网易号 > 正文 申请入驻

一文搞定!火山图在意不在形!

0
分享至
# ======================
# 火山图多风格整合代码
# 包含6种不同风格的火山图实现
# ======================

# 1. 环境设置与包加载 ----
rm(list = ls())
options(stringsAsFactors = F)

# 安装缺失的包
if (!requireNamespace("ggplot2", quietly = TRUE)) install.packages("ggplot2")
if (!requireNamespace("ggrepel", quietly = TRUE)) install.packages("ggrepel")
if (!requireNamespace("dplyr", quietly = TRUE)) install.packages("dplyr")
if (!requireNamespace("export", quietly = TRUE)) install.packages("export")
if (!requireNamespace("ggforce", quietly = TRUE)) install.packages("ggforce")
if (!requireNamespace("plotly", quietly = TRUE)) install.packages("plotly")
if (!requireNamespace("htmlwidgets", quietly = TRUE)) install.packages("htmlwidgets")
if (!requireNamespace("gridExtra", quietly = TRUE)) install.packages("gridExtra")

# 加载包
library(ggplot2)
library(ggrepel)
library(dplyr)
library(export)
library(ggforce)
library(plotly)
library(htmlwidgets)
library(gridExtra)

# 2. 创建模拟数据集 ----
set.seed(123)
n_genes <- 2000
dataset <- data.frame(
  gene = paste0("GENE", 1:n_genes),
  logFC = c(rnorm(n_genes*0.8, 0, 0.5), 
            rnorm(n_genes*0.1, 2, 0.5), 
            rnorm(n_genes*0.1, -2, 0.5)),
  P.Value = c(runif(n_genes*0.8, 0.01, 1), 
              runif(n_genes*0.2, 0.0001, 0.05))
)

# 添加变化类型和标签
dataset <- dataset %>%
  mutate(
    change = case_when(
      P.Value < 0.05 & logFC >= 1 ~ "Up",
      P.Value < 0.05 & logFC <= -1 ~ "Down",
      TRUE ~ "Stable"
    ),
    label = ifelse(change != "Stable", gene, "")
  )

# 3. 基础火山图 ----
basic_volcano <- ggplot(dataset, aes(logFC, -log10(P.Value))) +
  geom_point(aes(color = change), size = 2, alpha = 0.7) +
  scale_color_manual(values = c("Down" = "blue", "Stable" = "gray60", "Up" = "red")) +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "gray30") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "gray30") +
  labs(title = "Basic Volcano Plot",
       x = "log2(Fold Change)",
       y = "-log10(p-value)",
       color = "Expression") +
  theme_bw() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14),
    legend.position = "top"
  ) +
  geom_text_repel(
    data = dataset %>% filter(change != "Stable") %>% 
      slice_min(P.Value, n = 10),
    aes(label = label),
    size = 3,
    max.overlaps = 20
  )

# 4. 现代简约风格 ----
modern_volcano <- ggplot(dataset, aes(logFC, -log10(P.Value))) +
  geom_point(aes(fill = change, size = abs(logFC)), 
             shape = 21, color = "white", stroke = 0.3, alpha = 0.8) +
  scale_fill_manual(values = c("Down" = "#4E79A7", "Stable" = "gray80", "Up" = "#E15759")) +
  scale_size_continuous(range = c(1, 5), guide = "none") +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "gray40") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "gray40") +
  labs(title = "Modern Volcano Plot",
       x = "log2(Fold Change)",
       y = "-log10(p-value)",
       fill = "Expression") +
  theme_minimal() +
  theme(
    panel.grid.minor = element_blank(),
    panel.grid.major = element_line(color = "gray90"),
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    legend.position = "bottom"
  ) +
  ggrepel::geom_text_repel(
    data = dataset %>% filter(P.Value < 0.001 & abs(logFC) > 1.5),
    aes(label = label),
    size = 3.5,
    box.padding = 0.3,
    point.padding = 0.1,
    segment.color = "grey50"
  )

# 5. 学术黑白风格 ----
academic_volcano <- ggplot(dataset, aes(logFC, -log10(P.Value))) +
  geom_point(aes(shape = change), size = 2.5, alpha = 0.7, fill = "black") +
  scale_shape_manual(values = c("Down" = 25, "Stable" = 21, "Up" = 24)) +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed") +
  labs(title = "Academic Volcano Plot",
       x = "log2(Fold Change)",
       y = "-log10(p-value)",
       shape = "Expression") +
  theme_classic() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14),
    legend.position = "right",
    axis.line = element_line(color = "black"),
    axis.ticks = element_line(color = "black")
  ) +
  annotate("text", x = -2.5, y = -log10(0.05)+0.3, 
           label = "p = 0.05", size = 3) +
  annotate("text", x = 1.8, y = max(-log10(dataset$P.Value))-0.5, 
           label = "Up-regulated", size = 4, fontface = "italic") +
  annotate("text", x = -1.8, y = max(-log10(dataset$P.Value))-0.5, 
           label = "Down-regulated", size = 4, fontface = "italic")

# 6. 渐变火山图 ----
gradient_volcano <- ggplot(dataset, aes(logFC, -log10(P.Value))) +
  geom_point(aes(color = -log10(P.Value), size = abs(logFC)*0.8 + 1), 
             alpha = 0.8) +
  scale_color_gradientn(
    colours = c("#313695", "#4575B4", "#74ADD1", "#ABD9E9", "#E0F3F8", 
                "#FFFFBF", "#FEE090", "#FDAE61", "#F46D43", "#D73027", "#A50026"),
    name = "-log10(p-value)",
    limits = c(0, max(-log10(dataset$P.Value))),
    breaks = c(1, 2, 3, 4)
  ) +
  geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "gray30") +
  geom_vline(xintercept = c(-1, 1), linetype = "dashed", color = "gray30") +
  labs(title = "Gradient Volcano Plot",
       x = "log2(Fold Change)",
       y = "-log10(p-value)") +
  theme_bw() +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    legend.position = "right",
    panel.grid = element_line(color = "gray95")
  ) +
  ggrepel::geom_text_repel(
    data = dataset %>% filter(-log10(P.Value) > 3 & abs(logFC) > 1.5),
    aes(label = label),
    size = 3,
    box.padding = 0.4,
    segment.color = "grey40"
  )

# 7. 倾斜火山图(45度视角) ----
tilted_volcano <- ggplot(dataset, aes(logFC, -log10(P.Value))) +
  geom_point(aes(fill = change), 
             shape = 21, color = "white", size = 3, alpha = 0.7) +
  scale_fill_manual(values = c("Down" = "#1F77B4", "Stable" = "gray80", "Up" = "#FF7F0E")) +
  labs(title = "Tilted Volcano Plot (45° Perspective)",
       x = "log2(Fold Change)",
       y = "-log10(p-value)",
       fill = "Expression") +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14, margin = margin(b = 15)),
    legend.position = "bottom"
  ) +
  # 应用45度视角变换
  coord_trans(
    x = ggforce::trans_reverser("identity"),
    y = "identity"
  ) +
  # 添加对角线参考线
  geom_abline(slope = 1, intercept = 0, linetype = "dashed", alpha = 0.3, color = "gray40") +
  geom_abline(slope = -1, intercept = 0, linetype = "dashed", alpha = 0.3, color = "gray40") +
  # 添加阈值线
  geom_hline(yintercept = -log10(0.05), linetype = "dotted", alpha = 0.5) +
  geom_vline(xintercept = c(-1, 1), linetype = "dotted", alpha = 0.5) +
  # 添加象限标注
  annotate("text", x = -3, y = 5, label = "Low FC\nHigh Sig", size = 3.5, color = "gray30") +
  annotate("text", x = 3, y = 5, label = "High FC\nHigh Sig", size = 3.5, color = "gray30") +
  annotate("text", x = -3, y = 0.5, label = "Low FC\nLow Sig", size = 3.5, color = "gray30") +
  annotate("text", x = 3, y = 0.5, label = "High FC\nLow Sig", size = 3.5, color = "gray30")

# 8. 3D火山图(交互式) ----
# 添加第三维度数据(模拟表达量)
dataset$Expression <- rnorm(nrow(dataset), mean = 10, sd = 3) + abs(dataset$logFC)*2

# 创建颜色映射
color_map <- c("Up" = "#FF0000", "Down" = "#0000FF", "Stable" = "#CCCCCC")
dataset$color <- color_map[dataset$change]

# 创建3D火山图
volcano3d <- plot_ly(
  data = dataset,
  x = ~logFC,
  y = ~-log10(P.Value),
  z = ~Expression,
  type = "scatter3d",
  mode = "markers",
  marker = list(
    size = ~-log10(P.Value)*0.8 + 3,
    color = ~color,
    opacity = 0.7,
    line = list(width = 0)
  ),
  text = ~paste(
    "Gene: ", gene,
    " logFC: ", round(logFC, 3),
    " p-value: ", format.pval(P.Value, digits = 2),
    " Expression: ", round(Expression, 1)
  ),
  hoverinfo = "text"
) %>%
  layout(
    title = list(text = "3D Volcano Plot", y = 0.95),
    scene = list(
      xaxis = list(title = "log2(Fold Change)"),
      yaxis = list(title = "-log10(p-value)"),
      zaxis = list(title = "Expression Level"),
      camera = list(
        eye = list(x = 1.8, y = 1.8, z = 0.8)  # 调整视角
      )
    ),
    margin = list(l = 0, r = 0, b = 0, t = 40),
    showlegend = FALSE
  ) %>%
  add_annotations(
    x = 0.05,
    y = 0.95,
    xref = "paper",
    yref = "paper",
    text = "Color Legend: Red: Up-regulated Blue: Down-regulated",
    showarrow = FALSE,
    font = list(size = 12)
  )

# 9. 保存所有图形 ----
# 保存2D图形
graph2png(basic_volcano, "basic_volcano.png", width = 9, height = 7)
graph2png(modern_volcano, "modern_volcano.png", width = 9, height = 7)
graph2png(academic_volcano, "academic_volcano.png", width = 9, height = 7)
graph2png(gradient_volcano, "gradient_volcano.png", width = 10, height = 8)
graph2png(tilted_volcano, "tilted_volcano.png", width = 10, height = 8)

# 保存3D交互图
htmlwidgets::saveWidget(
  widget = volcano3d,
  file = "3D_volcano.html",
  selfcontained = TRUE
)

# 10. 并排显示2D图形 ----
grid_volcano <- gridExtra::grid.arrange(
  basic_volcano, 
  modern_volcano,
  academic_volcano,
  gradient_volcano,
  tilted_volcano,
  ncol = 3,
  top = "Comparative Volcano Plots"
)

# 保存组合图
graph2png(grid_volcano, "combined_volcano.png", width = 18, height = 12)

# 11. 在R中查看所有图形 ----
# 显示2D图形
print(basic_volcano)
print(modern_volcano)
print(academic_volcano)
print(gradient_volcano)
print(tilted_volcano)

# 显示3D图形(在RStudio中查看)
# volcano3d

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
我们应庆幸,美国总统是特朗普,如果换成希拉里结果将大不同!

我们应庆幸,美国总统是特朗普,如果换成希拉里结果将大不同!

观星赏月
2026-02-17 22:42:14
湖北一烟花爆竹销售点爆炸致12人遇难

湖北一烟花爆竹销售点爆炸致12人遇难

曹刚律师
2026-02-18 17:27:51
原地踏步16年的“政治明星”

原地踏步16年的“政治明星”

特例的猫
2026-02-18 13:22:50
美国传奇歌手John Legend首登央视春晚,分享演出及中国之行感受

美国传奇歌手John Legend首登央视春晚,分享演出及中国之行感受

草莓解说体育
2026-02-18 08:18:08
春晚机器人爆红背后:一场关于「非共识」的产业思辨

春晚机器人爆红背后:一场关于「非共识」的产业思辨

钛媒体APP
2026-02-18 09:38:16
各界祝贺苏翊鸣:国际雪联+中国队官方庆祝 佟丽娅许昕李现盛赞

各界祝贺苏翊鸣:国际雪联+中国队官方庆祝 佟丽娅许昕李现盛赞

醉卧浮生
2026-02-18 21:19:18
双鱼模型法:看美元兑人民币未来1年的走向趋势?2026.2.18wt

双鱼模型法:看美元兑人民币未来1年的走向趋势?2026.2.18wt

时尚的弄潮
2026-02-18 20:51:35
开始恐惧!全国统一的“春节噩梦”来了,网友:从初一吃到十五

开始恐惧!全国统一的“春节噩梦”来了,网友:从初一吃到十五

观察鉴娱
2026-02-18 17:42:06
3月1日全军施行:终身负责制权威解读,一看就懂

3月1日全军施行:终身负责制权威解读,一看就懂

Ck的蜜糖
2026-02-15 22:54:26
越南人吐槽:我们学的历史课,“中国”占据了80%,还要背诵唐诗

越南人吐槽:我们学的历史课,“中国”占据了80%,还要背诵唐诗

铭记历史呀
2026-01-28 02:21:58
春节来新加坡旅游,被自己穷笑了:酒店一晚1.6万、入境被罚6000

春节来新加坡旅游,被自己穷笑了:酒店一晚1.6万、入境被罚6000

新加坡万事通
2026-02-17 18:29:48
中日韩最大财团对比:三星3.2万亿,三菱21万亿,中国第一是谁?

中日韩最大财团对比:三星3.2万亿,三菱21万亿,中国第一是谁?

阿器谈史
2026-01-30 08:40:58
不少校长睡不着觉了,退休的也不行!

不少校长睡不着觉了,退休的也不行!

教而育之
2026-02-16 08:47:46
开年就封杀!从网红顶流到人人驱赶,房车为啥成了城市“公敌”

开年就封杀!从网红顶流到人人驱赶,房车为啥成了城市“公敌”

番外行
2026-02-13 08:58:27
2026年,按北京养老金计发基数12049元算,实际缴费18年领多少?

2026年,按北京养老金计发基数12049元算,实际缴费18年领多少?

碎月导师
2026-02-18 07:30:03
在ICU做了10年护士,发现一个秘密:放弃抢救时,签字越快哭得越凶

在ICU做了10年护士,发现一个秘密:放弃抢救时,签字越快哭得越凶

千秋文化
2026-02-14 20:45:52
2026上海不可错过的20件大事!

2026上海不可错过的20件大事!

周末做啥
2026-02-18 12:03:36
人民日报2次点名霍启刚,一个特殊称呼,让香港四大家族沉默了

人民日报2次点名霍启刚,一个特殊称呼,让香港四大家族沉默了

麦芽是个小趴菜
2025-12-26 00:42:49
痛心!29岁女子除夕去世,从小被父母抛弃,透析13年,长得很漂亮

痛心!29岁女子除夕去世,从小被父母抛弃,透析13年,长得很漂亮

离离言几许
2026-02-17 22:20:31
容祖儿晒霍汶希女儿近照,妈妈把她养的真好,15岁长得好港女

容祖儿晒霍汶希女儿近照,妈妈把她养的真好,15岁长得好港女

手工制作阿歼
2026-02-18 19:13:02
2026-02-18 22:15:00
芒果师兄 incentive-icons
芒果师兄
一起学习,共同成长,让生信助力科研。
492文章数 67关注度
往期回顾 全部

科技要闻

怒烧45亿,腾讯字节阿里决战春节

头条要闻

5位新能源车主春运开车出行 特斯拉车主:电车更好开

头条要闻

5位新能源车主春运开车出行 特斯拉车主:电车更好开

体育要闻

夺银被问丢金,谷爱凌回击外媒:很荒谬

娱乐要闻

6大卫视春晚收视出炉 北京台稳居第一

财经要闻

面条火腿香菇酱!上市公司这些年请你吃

汽车要闻

量产甲醇插混 吉利银河星耀6甲醇插混版申报图

态度原创

家居
艺术
亲子
公开课
军事航空

家居要闻

中古雅韵 乐韵伴日常

艺术要闻

竞赛入围:金砖国家新开发银行总部大楼,形如“绿叶”

亲子要闻

孩子防侵犯,妈妈光靠口头教育是没有用的

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

菲海警在南海投放不明物体 被中国海警全程监控并拍下

无障碍浏览 进入关怀版