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

使用cowplot的plot_grid实现对数Y轴ggplot图固定Y轴范围

解决cowplot组合对数Y轴散点图的Y轴范围统一问题

问题场景

要通过cowplot::plot_grid组合两张散点图,需求如下:

  • 两张图均使用对数Y轴(负数值会被自动过滤)
  • 两张图的Y轴范围完全对齐,达到facet_wrap(scales="fixed")的效果
  • 两张图的X轴需要设置不同的标签和刻度格式(比如给A的刻度加$符号,给B的加%符号),因此无法使用facet_wrap

此前尝试通过layer_scales获取图层范围后设置ylim,结果不符合预期,核心原因是对数轴的范围处理逻辑和线性轴不同。

可行方案

1. 先计算全局有效Y值范围

因为对数轴不支持负数,scale_y_log10会自动过滤负的Y值,所以需要从两张图的原始数据中,提取所有正Y值,计算它们的全局最小值和最大值,作为统一的Y轴范围。

2. 通过scale_y_log10(limits = ...)设置统一范围

不要使用ylim(),因为ylim是针对原始数据的线性范围,而scale_y_log10的limits参数是专门适配对数轴的范围设置,能保证轴的显示逻辑正确。

完整代码示例

library(tidyverse)
library(cowplot)

# 生成示例数据
data_a <- tibble(x = rnorm(100), y = rnorm(100), type = "A")
data_b <- tibble(x = rnorm(100, mean = 10), y = rnorm(100, mean = 10), type = "B")

# 计算全局有效Y值范围(仅保留正数值)
global_y_lims <- c(
  min(c(data_a$y[data_a$y > 0], data_b$y[data_b$y > 0])),
  max(c(data_a$y[data_a$y > 0], data_b$y[data_b$y > 0]))
)

# 绘制图A:自定义X轴格式 + 统一对数Y轴范围
plot_a <- data_a %>%
  ggplot(aes(y = y, x = x)) +
  geom_point() +
  scale_y_log10(limits = global_y_lims) +
  scale_x_continuous(labels = ~paste0("$", .x))  # X轴刻度添加$符号

# 绘制图B:自定义X轴格式 + 统一对数Y轴范围
plot_b <- data_b %>%
  ggplot(aes(y = y, x = x)) +
  geom_point() +
  scale_y_log10(limits = global_y_lims) +
  scale_x_continuous(labels = ~paste0(.x, "%"))  # X轴刻度添加%符号

# 组合两张图
plot_grid(plot_a, plot_b)

原方法失效的原因

  • layer_scales(a)$y$range$range获取的是图层经过对数转换后的轴范围,直接用这个值设置ylim会破坏对数轴的显示逻辑,因为ylim是基于原始数据的线性范围,而非对数转换后的轴刻度范围。
  • 只有从原始数据中提取未被过滤的正Y值,计算全局范围后,通过scale_y_log10的limits参数设置,才能保证两张图的对数Y轴范围完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 03:54:28