首页 > 解决方案 > matplotlib tight_layout() 的替代品?或者停止 xlabels 超出图表边缘?

问题描述

我正在尝试在 seaborn 中创建条形图的动画。

当我迭代数据时,创建并保存每个唯一日期条形图而不使用tight_layout == True,每件事都保持静止,但有些标签被剪掉了。

使用tight_layout == True 非常棒,它解决了所有这些问题,但有一个不良后果。

随着数据值的增加,X 刻度标签会发生变化,matplot lib 会自动格式化刻度的位置,这会产生很好的结果但有时最终标签会超出图表边缘,这会导致紧密布局减少图表的宽度以腾出空间标签。有没有办法在保持图表宽度不变的同时使用tight_layout?

这可以。

              |
              |
              |
              |
              |
______________|
       |
   500,000

这给我带来了一个问题,因为 xticklabel 超出了图表边缘,减小了图表的宽度,使其与 figsize 匹配。

           |
           |
           |
           |
           |
___________|
          |
       500,000

也许如果有人知道如何判断 xticklabel 的 xpos > 图表宽度,那么我可以删除该实例中的最后一个刻度。但我似乎无法掌握这些信息。

标签: pythonmatplotlibseaborn

解决方案


好的,我已经设法解决了这个问题。对于任何在这里阅读本文的人都是我的解决方案。

创建一些假数据。

df = pd.DataFrame({"Category":[f"TESTING LABELS {x}" for x in range(30)]})
df["Data"] = np.random.randint(0,9999,len(df))
df

绘制图表

fig = plt.figure(figsize=(10,8),dpi=100)
ax = sns.barplot(x="Category", y="Data",data=df)

请注意标签如何超出图表边缘。

标签测试

这可以通过首先获取图表宽度(不是图形宽度)然后遍历标签宽度并丢弃任何>图表宽度来解决。

有两个选项可以删除超出的标签留下刻度

__________________________
|          |             |
value1    value2

或者

完全去除蜱虫。

__________________________
|          |             
value1    value2

首先获取图表(您需要调用 draw() 否则会失败)

fig = plt.figure(figsize=(10,8),dpi=100)
ax = sns.barplot(x="Category", y="Data",data=df)
ax.get_figure().canvas.draw()

获取图表宽度

chart_x1 = ax.get_window_extent().x1

然后使用列表推导删除任何溢出。

删除标签

ticks = [tick for tick in ax.get_xticklabels() if tick.get_window_extent().x1 < chart_x1]
_ = ax.set_xticklabels(ticks)

标签去除

删除刻度

ticks = [tick.get_position()[0] for tick in ax.get_xticklabels() if tick.get_window_extent().x1 < chart_x1]
_ = ax.set_xticks(ticks)

在此处输入图像描述

只是指出您可能不想删除条形下方的此标签,但在我的特定情况下,条形是水平的(此演示不是)

溢出刻度标签删除的完整代码示例:

#set size
fig = plt.figure(figsize=(10,8),dpi=100)
#define data and get axis
ax = sns.barplot(x="Category", y="Data",data=df)
#draw prior to x position retrieval 
ax.get_figure().canvas.draw()
#chart max chart width
chart_x1 = ax.get_window_extent().x1
#use list comprehension to only select values that do not overrun 
ticks = [tick for tick in ax.get_xticklabels() if tick.get_window_extent().x1 < chart_x1]
#then set the tick labels
_ = ax.set_xticklabels(ticks)

推荐阅读