You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ggplot实现非均匀断点的等间距图例刻度

问题

使用geom_point绘制频率(Frequency)和倍数变化(FC)两个变量:点大小对应Frequency,颜色对应FC(FC<1.5为绿色,>1.5为红色)。为区分FC小于1的部分设置了更多断点,绘图效果符合预期,但希望让刻度c(0, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6)在图例颜色条中呈现等间距,求实现方法。

原绘图代码及可复现样本数据如下:

原绘图代码

p <- ggplot(mainG, aes(x = Allele, y = Cohort, size = Freq, color = FC)) +
  geom_point() +
  scale_y_discrete(limits = rev(levels(mainG$Cohort)), position = "right") +
  scale_size_continuous(limits = c(0, 0.5), breaks = c(0, 0.05, 0.10, 0.20, 0.40)) +
  # Underrepresented: FC < 1.5 ; overrepresented: FC > 1.5
  scale_colour_gradientn(
    colours = c('darkgreen', 'forestgreen', 'darkseagreen3', 'darkseagreen2',
              'indianred1', 'indianred2', 'indianred3', 'darkred'),
    values = c(0, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6)/6,
    breaks = c(0, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6)) +
  xlab("") + ylab("") +
  theme(axis.text = element_text(size = 7),
        axis.text.x = element_text(angle = 45, vjust = 1, hjust=1),
        axis.ticks.y = element_blank(),
        panel.border = element_rect(fill = NA),
        panel.background = element_blank(),
        axis.line = element_line(), 
        legend.title = element_text(size = 7),
        legend.text = element_text(size = 7),
        legend.key = element_blank(), 
        legend.position = "right",
        panel.spacing = unit(0.2, "lines"), 
        strip.background =element_rect(colour = "black", fill = NA),
        strip.text = element_text(size = 7, face = "bold", margin = margin(0.1,5,0.1,5, "cm"))
  ) +
  facet_grid(.~ Gene, scales = "free", space = "free")

p + guides(colour = guide_colourbar(barwidth = unit(0.5, "cm"), barheight = unit(5, "cm"), 
                                    direction = "vertical"),
           size = guide_legend(title = "Frequency", reverse = T))

可复现样本数据

Cohort  Gene    Allele  Freq    FC
Cohort1 B   *08:01  0.027   0.24
Cohort2 A   *01:01  0.103   0.63
Cohort2 A   *68:01  0.103   3.63
Cohort2 B   *07:02  0.207   1.59
Cohort2 B   *08:01  0.034   0.31
Cohort2 B   *51:01  0.121   2.44
Cohort3 A   *02:01  0.407   1.51
Cohort3 A   *03:01  0   NA
Cohort3 B   *07:02  0.037   0.28
Cohort3 B   *08:01  0.019   0.17
Cohort3 B   *44:03  0.148   3.15
Cohort4 A   *02:01  0.17    0.63
Cohort4 A   *24:02  0.17    2.01
Cohort4 B   *07:02  0.05    0.38
Cohort4 B   *18:01  0.11    2.41
Cohort5 B   *07:02  0.053   0.4
Cohort5 B   *18:01  0.105   2.31
Cohort6 B   *07:02  0.041   0.31
Cohort6 B   *18:01  0.122   2.69
Cohort6 B   *51:01  0.102   2.06
Control A   *01:01  0.163   NA
Control A   *02:01  0.269   NA
Control A   *03:01  0.14    NA
Control A   *24:02  0.085   NA
Control A   *26:01  0.035   NA
Control A   *29:02  0.035   NA
Control A   *32:01  0.037   NA
Control A   *68:01  0.029   NA
Control B   *07:02  0.13    NA
Control B   *08:01  0.11    NA
Control B   *18:01  0.046   NA
Control B   *44:02  0.087   NA
Control B   *44:03  0.047   NA
Control B   *51:01  0.05    NA

解决方案

要实现指定刻度在颜色条中等间距显示,核心是对FC值做自定义非线性变换,让目标断点对应到颜色条的等间距位置,同时保留原有颜色映射逻辑。

修改后的完整代码

library(ggplot2)

# 读取样本数据
mainG <- read.table(text = "Cohort  Gene    Allele  Freq    FC
Cohort1 B   *08:01  0.027   0.24
Cohort2 A   *01:01  0.103   0.63
Cohort2 A   *68:01  0.103   3.63
Cohort2 B   *07:02  0.207   1.59
Cohort2 B   *08:01  0.034   0.31
Cohort2 B   *51:01  0.121   2.44
Cohort3 A   *02:01  0.407   1.51
Cohort3 A   *03:01  0   NA
Cohort3 B   *07:02  0.037   0.28
Cohort3 B   *08:01  0.019   0.17
Cohort3 B   *44:03  0.148   3.15
Cohort4 A   *02:01  0.17    0.63
Cohort4 A   *24:02  0.17    2.01
Cohort4 B   *07:02  0.05    0.38
Cohort4 B   *18:01  0.11    2.41
Cohort5 B   *07:02  0.053   0.4
Cohort5 B   *18:01  0.105   2.31
Cohort6 B   *07:02  0.041   0.31
Cohort6 B   *18:01  0.122   2.69
Cohort6 B   *51:01  0.102   2.06
Control A   *01:01  0.163   NA
Control A   *02:01  0.269   NA
Control A   *03:01  0.14    NA
Control A   *24:02  0.085   NA
Control A   *26:01  0.035   NA
Control A   *29:02  0.035   NA
Control A   *32:01  0.037   NA
Control A   *68:01  0.029   NA
Control B   *07:02  0.13    NA
Control B   *08:01  0.11    NA
Control B   *18:01  0.046   NA
Control B   *44:02  0.087   NA
Control B   *44:03  0.047   NA
Control B   *51:01  0.05    NA", header = TRUE, stringsAsFactors = FALSE)

# 定义自定义变换:将目标断点映射到等间距的0-1区间
fc_breaks <- c(0, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5, 6)
fc_trans <- scales::trans_new(
  name = "fc_custom",
  transform = function(x) {
    idx <- findInterval(x, fc_breaks)
    ifelse(idx == 0, 0,
           ifelse(idx == length(fc_breaks), 1,
                  (idx - 1 + (x - fc_breaks[idx])/(fc_breaks[idx+1]-fc_breaks[idx]))/(length(fc_breaks)-1))
           )
  },
  inverse = function(x) {
    idx <- floor(x*(length(fc_breaks)-1)) + 1
    if(idx >= length(fc_breaks)) return(fc_breaks[length(fc_breaks)])
    fc_breaks[idx] + (x*(length(fc_breaks)-1) - (idx-1))*(fc_breaks[idx+1]-fc_breaks[idx])
  }
)

# 绘制图形
p <- ggplot(mainG, aes(x = Allele, y = Cohort, size = Freq, color = FC)) +
  geom_point() +
  scale_y_discrete(limits = rev(levels(factor(mainG$Cohort))), position = "right") +
  scale_size_continuous(limits = c(0, 0.5), breaks = c(0, 0.05, 0.10, 0.20, 0.40)) +
  # 调整颜色映射,使用自定义变换
  scale_colour_gradientn(
    colours = c('darkgreen', 'forestgreen', 'darkseagreen3', 'darkseagreen2',
                'indianred1', 'indianred2', 'indianred3', 'darkred'),
    values = seq(0, 1, length.out = length(fc_breaks)),  # 等间距颜色位置
    breaks = fc_breaks,  # 指定目标断点
    trans = fc_trans  # 应用自定义变换
  ) +
  xlab("") + ylab("") +
  theme(axis.text = element_text(size = 7),
        axis.text.x = element_text(angle = 45, vjust = 1, hjust=1),
        axis.ticks.y = element_blank(),
        panel.border = element_rect(fill = NA),
        panel.background = element_blank(),
        axis.line = element_line(), 
        legend.title = element_text(size = 7),
        legend.text = element_text(size = 7),
        legend.key = element_blank(), 
        legend.position = "right",
        panel.spacing = unit(0.2, "lines"), 
        strip.background =element_rect(colour = "black", fill = NA),
        strip.text = element_text(size = 7, face = "bold", margin = margin(0.1,5,0.1,5, "cm"))
  ) +
  facet_grid(.~ Gene, scales = "free", space = "free")

# 调整颜色条指南,确保刻度显示正确
p + guides(colour = guide_colourbar(barwidth = unit(0.5, "cm"), barheight = unit(5, "cm"), 
                                    direction = "vertical", breaks = fc_breaks),
           size = guide_legend(title = "Frequency", reverse = TRUE))

关键说明

  1. 自定义变换函数:fc_trans将FC值映射到0-1的等间距区间,让目标断点在颜色条上均匀分布,逆变换则负责将映射后的值还原为原始FC刻度。
  2. 颜色映射调整:values设置为等间距的0-1序列,确保每个颜色对应到刻度的等间距位置,和断点一一匹配。
  3. 保留原有逻辑:完全保留了FC<1.5用绿色系、>1.5用红色系的颜色规则,同时让小值刻度占据更多视觉空间,满足区分需求。

内容的提问来源于stack exchange,提问作者jennwl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:57:38