Matplotlib中裁剪绘图坐标轴:缩小散点图两组数据间隙
解决Y轴两组数据间隙过大的方案:Y轴断裂(Broken Y-axis)
Hey there! 你说的这个操作通常叫做Y轴断裂(broken Y-axis)或者截断Y轴——核心就是把Y轴中间不需要的空白区间(比如你的案例里的20-90)“砍掉”,让上下两组数据更紧凑地展示,同时保留数据的真实范围,避免误导读者。
下面给你几个主流绘图工具的具体实现方案:
Python(Matplotlib)
Matplotlib没有原生的一键断裂轴功能,但可以通过创建两个垂直拼接的子图来模拟,中间用断裂标记提示:
import matplotlib.pyplot as plt import numpy as np # 生成模拟数据 x = np.random.uniform(0, 1, 50) y_low = np.random.uniform(10, 20, 50) y_high = np.random.uniform(90, 100, 50) # 创建画布和两个子图,上下排列 fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True, figsize=(8, 6), gridspec_kw={'height_ratios': [1, 1]}) # 绘制上下两组数据 ax1.scatter(x, y_high) ax2.scatter(x, y_low) # 设置Y轴范围,砍掉中间的空白 ax1.set_ylim(85, 105) ax2.set_ylim(5, 25) # 添加断裂标记(//) ax1.spines['bottom'].set_visible(False) ax2.spines['top'].set_visible(False) ax1.tick_params(axis='x', bottom=False) # 隐藏上方子图的X轴刻度 # 绘制断裂的斜线 d = .015 # 斜线的长度和角度 kwargs = dict(transform=ax1.transAxes, color='k', clip_on=False) ax1.plot((-d, +d), (-d, +d), **kwargs) ax1.plot((1 - d, 1 + d), (-d, +d), **kwargs) kwargs.update(transform=ax2.transAxes) ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs) ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs) # 添加标题和标签 fig.suptitle('Broken Y-axis Scatter Plot') ax2.set_xlabel('X Variable (0-1)') fig.text(0.04, 0.5, 'Y Variable', va='center', rotation='vertical') plt.tight_layout() plt.show()
R(ggplot2 + ggbreak)
R里可以用专门的ggbreak包来快速实现断裂轴,非常方便:
# 先安装包(第一次用需要安装) # install.packages("ggbreak") library(ggplot2) library(ggbreak) # 生成模拟数据 set.seed(123) df <- data.frame( x = runif(100), y = c(runif(50, 10, 20), runif(50, 90, 100)) ) # 绘制带断裂Y轴的散点图 ggplot(df, aes(x, y)) + geom_point() + scale_y_break(breaks = c(25, 85), scales = 1) + # 设置断裂的区间(25到85之间被截断) labs(title = "Broken Y-axis Scatter Plot", x = "X Variable (0-1)", y = "Y Variable") + theme_bw()
注意事项
- 一定要明确标注Y轴是断裂的(比如用//标记),避免读者误以为两组数据的差距很小,这是断裂轴最关键的原则!
- 如果你的数据适合用对数轴展示,也可以考虑把Y轴改成对数刻度,同样能缩小两组数据的视觉间隙,而且不需要截断轴,比如
plt.yscale('log')(Matplotlib)或者scale_y_log10()(ggplot2)。
内容的提问来源于stack exchange,提问作者Danii-Sh
相关产品推荐
相关产品推荐

