我正在 matplotlib 中处理一个(相当复杂的)条形图。它包含来自多个源的摘要数据,每个源都沿 x 轴标记,y 轴上有一系列结果。许多结果都是异常值,我尝试使用断开的 y 轴来显示这些结果,而不会使用以下组合来扭曲整个图表这个方法 https://matplotlib.org/gallery/subplots_axes_and_figures/broken_axis.html用于插入损坏的 y 轴,
和这个方法 https://matplotlib.org/gallery/subplots_axes_and_figures/gridspec_multicolumn.html用于对齐网格上的子图(异常值集中在特定点周围,因此上面的图可能非常小)。
结果图看起来有点像这样
问题在于,对角线在 y 轴断裂上方和下方的角度明显不同。我不明白为什么。
我正在使用的代码如下。对于复杂性表示歉意,我必须对不同的轴进行大量修改才能完成这项工作......
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.gridspec import GridSpec
data = pd.DataFrame.from_dict(
{
"low": {
"Record 1": 5,
"Record 2": 10,
"Record 3": 15,
"Record 4": 20,
"Record 5": 25,
"Record 6": 30,
"Record 7": 35,
"Record 8": 40,
"Record 9": 45,
"Record 10": 50,
},
"high": {
"Record 1": 25,
"Record 2": 100,
"Record 3": 225,
"Record 4": 25,
"Record 5": 100,
"Record 6": 10000,
"Record 7": 25,
"Record 8": 100,
"Record 9": 225,
"Record 10": 25,
},
}
)
mm = (146, 90) # x value then y value
inches = (mm[0] / 25.4, mm[1] / 25.4)
fig = plt.figure(figsize=inches)
fig.text(0.02, 0.6, r"Y axis label", va="center", rotation="vertical", fontsize=12)
gs = GridSpec(2, 2, height_ratios=[1, 4])
ax = fig.add_subplot(gs.new_subplotspec((0, 0), colspan=2))
ax2 = fig.add_subplot(gs.new_subplotspec((1, 0), colspan=2))
palette = plt.get_cmap("tab20")
indx = np.arange(len(data.index))
labs = data.index.tolist()
labs.insert(0, "")
ax.tick_params(axis="both", which="major", labelsize=10)
ax2.tick_params(axis="both", which="major", labelsize=10)
ax2.set_xticklabels((labs), rotation=45, fontsize=10, horizontalalignment="right")
ax.set_xticklabels(())
ax.set_xticks(np.arange(-1, len(data.index) + 1, 1.0))
ax2.set_xticks(np.arange(-1, len(data.index) + 1, 1.0))
ax.set_yticks(np.arange(0, max(data["high"]) + 10, 100))
ax2.set_yticks(np.arange(0, max(data["high"]) + 10, 100))
# plot the same data on both axes
bar_lower = ax2.bar(
x=indx,
height=data["high"] - data["low"],
bottom=data["low"],
width=-0.5,
align="center",
color=palette(1),
edgecolor="k",
linewidth=0.5,
zorder=10,
)
bar_upper = ax.bar(
x=indx,
height=data["high"] - data["low"],
bottom=data["low"],
width=-0.5,
align="center",
color=palette(1),
edgecolor="k",
linewidth=0.5,
zorder=10,
)
# zoom-in / limit the view to different portions of the data
ax.set_ylim(9950, 10050) # outliers only
ax2.set_ylim(0, 450) # most of the data
ax.set_xlim(-0.5, len(data.index) - 0.25) # outliers only
ax2.set_xlim(-0.5, len(data.index) - 0.25) # most of the data
ax.spines["bottom"].set_visible(False)
ax2.spines["top"].set_visible(False)
ax.grid(color="k", alpha=0.5, linestyle=":", zorder=1)
ax2.grid(color="k", alpha=0.5, linestyle=":", zorder=1)
ax.tick_params(axis="x", which="both", length=0)
ax.tick_params(labeltop="off")
ax2.tick_params(labeltop="off")
ax2.xaxis.tick_bottom()
d = 0.015 # how big to make the diagonal lines in axes coordinates
# arguments to pass to plot, just so we don't keep repeating them
kwargs = dict(transform=ax.transAxes, color="k", clip_on=False) # linewidth=1)
ax.plot((-d, +d), (-d, +d), **kwargs) # top-left diagonal
ax.plot((1 - d, 1 + d), (-d, +d), **kwargs) # top-right diagonal
kwargs.update(transform=ax2.transAxes) # switch to the bottom axes
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs) # bottom-left diagonal
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs) # bottom-right diagonal
plt.subplots_adjust(
top=0.943, bottom=0.214, left=0.103, right=0.97, hspace=0.133, wspace=0.062
)
plt.show()