使用ggplot2基于分段值绘制拷贝数增减散点图
解决方案:用R ggplot2实现拷贝数分段散点可视化
步骤1:准备环境与数据
首先加载所需工具包:
library(ggplot2) library(dplyr) library(tidyr)
我们需要染色体长度和着丝粒位置数据来区分染色体臂、计算X轴缩放位置,以下是hg19版本的参考数据(如果用hg38可替换对应数值):
# 1-22号染色体长度(hg19) chr_length <- tibble( chrom = as.character(1:22), length = c(249250621, 243199373, 198022430, 191154276, 180915260, 171115067, 159138663, 146364022, 141213431, 135534747, 135006516, 133851895, 115169878, 107349540, 102531392, 90354753, 81195210, 78077248, 59128983, 63025520, 48129895, 51304566) ) # 1-22号染色体着丝粒位置(hg19,用于区分p/q臂) centromeres <- tibble( chrom = as.character(1:22), cent_pos = c(125000000, 93300000, 91000000, 50400000, 48400000, 61000000, 59900000, 45600000, 49000000, 40200000, 53700000, 35800000, 17900000, 17600000, 19000000, 36600000, 24000000, 17200000, 26500000, 27500000, 13200000, 14700000) )
假设你的原始数据框名为cnv_data,先做数据预处理:
注意:如果你的原始数据列名是
sampleID、chromosome,请将代码中对应的chrom替换为chromosome,确保列名匹配
cnv_processed <- cnv_data %>% # 仅保留1-22号常染色体 filter(chrom %in% as.character(1:22)) %>% mutate(chrom = as.character(chrom)) %>% # 合并染色体长度、着丝粒数据 left_join(chr_length, by = "chrom") %>% left_join(centromeres, by = "chrom") %>% # 判断分段属于p臂还是q臂 mutate(arm = ifelse(end.pos <= cent_pos, "p", "q")) %>% # 计算每个染色体在X轴的起始偏移(累计前序染色体总长度) group_by(chrom) %>% mutate(chr_start = sum(chr_length$length[chr_length$chrom < unique(chrom)])) %>% ungroup() %>% # 用分段中点作为散点在X轴的位置 mutate(x_pos = chr_start + (start.pos + end.pos)/2)
步骤2:绘制可视化图
先定义增益/损失的阈值(可根据需求自定义):
gain_threshold <- 0.2 loss_threshold <- -0.2
接着绘制主图,先画染色体臂背景色块,再叠加散点:
# 准备染色体背景数据(用于绘制X轴的臂区分色块) chr_background <- chr_length %>% left_join(centromeres, by = "chrom") %>% mutate(chr_start = sum(chr_length$length[chr_length$chrom < chrom]), p_end = chr_start + cent_pos, q_start = p_end, q_end = chr_start + length) %>% select(chrom, chr_start, p_end, q_start, q_end) %>% pivot_longer(cols = c(chr_start:p_end, q_start:q_end), names_to = c("arm", ".value"), names_pattern = "(.*)_(start|end)") # 生成最终可视化图 ggplot() + # 绘制染色体臂背景,区分p/q臂颜色 geom_rect(data = chr_background, aes(xmin = start, xmax = end, ymin = -Inf, ymax = Inf, fill = arm), alpha = 0.2) + # 绘制CNV分段散点,按阈值标记增益/损失/中性 geom_point(data = cnv_processed, aes(x = x_pos, y = seg.mean, color = case_when( seg.mean > gain_threshold ~ "Gain", seg.mean < loss_threshold ~ "Loss", TRUE ~ "Neutral" )), size = 2, alpha = 0.8) + # 设置颜色映射 scale_fill_manual(values = c("p" = "#e0e0e0", "q" = "#c0c0c0")) + scale_color_manual(values = c("Gain" = "#ff4444", "Loss" = "#3366ff", "Neutral" = "#666666")) + # 调整X轴:用染色体编号替换原始位置值,刻度对应染色体中点 scale_x_continuous(breaks = chr_length$chr_start + chr_length$length/2, labels = chr_length$chrom) + # 设置坐标轴与图例标签 labs(x = "Chromosome", y = "Segment Mean", color = "CNV Status", fill = "Chromosome Arm") + # 优化主题样式 theme_minimal() + theme( axis.text.x = element_text(size = 10), panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank() )
关键说明
- X轴宽度完全匹配染色体实际长度,满足"按染色体尺寸设置厚度"的需求
- 通过着丝粒位置自动区分p/q臂,背景色块直观展示臂分布
- 散点颜色根据自定义阈值自动标记增益、损失和中性区域
- 若切换基因组版本(如hg38),只需替换
chr_length和centromeres中的数值即可
内容的提问来源于stack exchange,提问作者shweta godbole
相关产品推荐
相关产品推荐

