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

Matplotlib:add_gridspec布局下如何让同行饼图占满垂直空间

问题描述

尝试绘制2×2的不同类型子图网格,当同一行包含柱状图和饼图时,若柱状图的轴标签过长,会占据大量空间导致柱子变小(此情况可接受),但同行的饼图会随之调整尺寸。希望让饼图使用全部垂直空间。已将问题简化为单行2个子图的示例,最终版本为2行布局且同列子图宽度不一定相同,因此使用add_gridspec而非简单的subplots(2,2)。

示例代码如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# Set the seed for reproducibility
np.random.seed(42)

# Define the list of countries
countries = ['USA', 'Canada', 'Germany', 'France', 'Japan', 'Australia', 'Brazil', 'India', 'China', 'Mexico']

# Add a country with a long name
countries.append('United Kingdom of Great Britain and Northern Ireland')

# Define the list of possible statuses
statuses = ['Active', 'Inactive', 'Error', 'Warning']

# Generate random data
data = {
    'Country': np.random.choice(countries, 500),
    'Status': np.random.choice(statuses, 500)
}

# Create the DataFrame
df = pd.DataFrame(data)

# Create the figure and axes
fig = plt.figure(layout="constrained", figsize=(10, 8))

gs0 = fig.add_gridspec(1, 2)
ax1 = fig.add_subplot(gs0[0])
ax2 = fig.add_subplot(gs0[1])

# Plot the data
df.reset_index().pivot_table('index', 'Country', 'Status', aggfunc='count').plot.bar(stacked=True, ax=ax1)
ax1.legend(loc='center left',bbox_to_anchor=(1.0, 0.5))

s = df.Status.value_counts()
s.plot.pie(ax=ax2)

当前效果:
当前子图布局效果

解决方案

要让饼图充分利用垂直空间,核心是让饼图所在的坐标轴保持正方形比例,同时不受左侧柱状图标签的挤压影响,以下是两种实用方法:

方法1:直接设置饼图坐标轴宽高比

在绘制饼图后,为坐标轴添加固定宽高比设置,强制饼图保持圆形并填充可用垂直空间:

# 绘制饼图后添加该行代码
ax2.set_aspect('equal', adjustable='box')

这个设置会让饼图强制维持圆形,同时自动调整子图框的尺寸来适配这个比例,最大限度利用垂直空间。

方法2:嵌套Gridspec精细化布局控制

如果后续需要扩展为2行多列的复杂布局,可以通过嵌套Gridspec为饼图单独分配空间,确保其不受其他子图的布局干扰:

# 修改Gridspec创建逻辑
fig = plt.figure(layout="constrained", figsize=(10, 8))
gs0 = fig.add_gridspec(1, 2)

# 柱状图子图
ax1 = fig.add_subplot(gs0[0])
# 为饼图创建嵌套Gridspec,确保空间独立控制
gs_pie = gs0[1].subgridspec(1, 1)
ax2 = fig.add_subplot(gs_pie[0])
ax2.set_aspect('equal')

这种方式适合后续调整不同行、列的子图尺寸比例,灵活性更高。

优化后的完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)

countries = ['USA', 'Canada', 'Germany', 'France', 'Japan', 'Australia', 'Brazil', 'India', 'China', 'Mexico']
countries.append('United Kingdom of Great Britain and Northern Ireland')
statuses = ['Active', 'Inactive', 'Error', 'Warning']

data = {
    'Country': np.random.choice(countries, 500),
    'Status': np.random.choice(statuses, 500)
}
df = pd.DataFrame(data)

fig = plt.figure(layout="constrained", figsize=(10, 8))
gs0 = fig.add_gridspec(1, 2)
ax1 = fig.add_subplot(gs0[0])
ax2 = fig.add_subplot(gs0[1])

# 绘制柱状图
df.reset_index().pivot_table('index', 'Country', 'Status', aggfunc='count').plot.bar(stacked=True, ax=ax1)
ax1.legend(loc='center left', bbox_to_anchor=(1.0, 0.5))

# 绘制饼图并设置宽高比
s = df.Status.value_counts()
s.plot.pie(ax=ax2)
ax2.set_aspect('equal', adjustable='box')

plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:50:21