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

如何在Matplotlib柱状图中按双变量分组X轴(避免重复)

在Matplotlib柱状图中实现国家-城市的分组X轴标签

我需要在Matplotlib制作的柱状图X轴上按「国家、城市」两个变量分组,但当前代码会把两个变量拼接,导致国家名称重复,不符合需求。以下是相关数据代码、绘图代码,以及当前和期望的图表效果。


数据代码

import pandas as pd
import random

# 欧洲国家列表
paises_europa = ['España', 'Francia', 'Alemania', 'Italia', 'Reino Unido', 'Portugal', 'Países Bajos']

# 对应每个国家的城市列表
ciudades = [['Madrid', 'Barcelona'],
            ['París'],
            ['Berlín', 'Múnich', 'Hamburgo'],
            ['Roma', 'Milán'],
            ['Londres', 'Birmingham', 'Manchester'],
            ['Lisboa', 'Oporto'],
            ['Ámsterdam', 'Róterdam']]

# 创建国家-城市-店铺数的关联列表
data = []
for pais, lista_ciudades in zip(paises_europa, ciudades):
    for ciudad in lista_ciudades:
        data.append((pais, ciudad, random.randint(5, 50)))

# 生成DataFrame
df = pd.DataFrame(data, columns=['Pais', 'Ciudad', 'Tiendas'])

原绘图代码

import matplotlib.pyplot as plt

# 计算柱状图最大值
max_valor = df['Tiendas'].max()

# 设置Y轴范围
y_min = 0
y_max = max_valor + 5

# 创建画布和坐标轴
fig, ax = plt.subplots(figsize=(12, 6))

# 定义柱状图颜色
bar_color = '#4a8a52'

# 绘制柱状图
ax.bar(df.index, df['Tiendas'], color=bar_color)

# 设置X轴刻度和标签(拼接国家和城市,导致重复)
ax.set_xticks(df.index)
ax.set_xticklabels([f'{pais} - {ciudad}' for pais, ciudad in zip(df['Pais'], df['Ciudad'])], rotation=90)

# 设置Y轴范围
ax.set_ylim(y_min, y_max)

# Y轴显示整数刻度
ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))

# 设置图表标题
plt.title('Count of Stores by Country and City')

# 设置X轴标签
ax.set_xlabel('Country / City')

# 设置Y轴标签
ax.set_ylabel('Stores')

# 为柱状图添加数值标签
for i, val in enumerate(df['Tiendas']):
    ax.text(i, val + 1, str(val), ha='center', va='bottom', fontsize=10)

# 调整布局
plt.tight_layout()

# 显示图表
plt.show()

当前与期望效果

当前图表效果

当前柱状图效果

期望图表效果

期望的分组柱状图效果


解决方案

要实现国家分组、仅显示一次国家名称的X轴布局,我们可以通过双X轴的方式实现:下方轴显示城市,上方轴按分组居中显示国家名称,避免重复。

修改后的完整绘图代码

import matplotlib.pyplot as plt
import pandas as pd
import random

# ---------------------- 保留原数据生成逻辑 ----------------------
paises_europa = ['España', 'Francia', 'Alemania', 'Italia', 'Reino Unido', 'Portugal', 'Países Bajos']
ciudades = [['Madrid', 'Barcelona'],
            ['París'],
            ['Berlín', 'Múnich', 'Hamburgo'],
            ['Roma', 'Milán'],
            ['Londres', 'Birmingham', 'Manchester'],
            ['Lisboa', 'Oporto'],
            ['Ámsterdam', 'Róterdam']]

data = []
for pais, lista_ciudades in zip(paises_europa, ciudades):
    for ciudad in lista_ciudades:
        data.append((pais, ciudad, random.randint(5, 50)))
df = pd.DataFrame(data, columns=['Pais', 'Ciudad', 'Tiendas'])
# ------------------------------------------------------------------

# 绘图核心逻辑
max_valor = df['Tiendas'].max()
y_min = 0
y_max = max_valor + 5

fig, ax = plt.subplots(figsize=(12, 6))
bar_color = '#4a8a52'

# 绘制柱状图
ax.bar(df.index, df['Tiendas'], color=bar_color)

# ---------------------- 核心修改:分组X轴设置 ----------------------
# 1. 下方X轴:显示城市名称,优化旋转角度提升可读性
ax.set_xticks(df.index)
ax.set_xticklabels(df['Ciudad'], rotation=45, ha='right')
ax.set_xlabel('Ciudad')

# 2. 上方X轴:显示国家分组,居中对齐对应城市组
ax2 = ax.twiny()
country_positions = []
country_labels = []
current_idx = 0

# 计算每个国家分组的中心位置
for pais in paises_europa:
    city_count = len(df[df['Pais'] == pais])
    center_pos = current_idx + (city_count - 1) / 2
    country_positions.append(center_pos)
    country_labels.append(pais)
    current_idx += city_count

# 设置上方X轴的刻度与标签
ax2.set_xticks(country_positions)
ax2.set_xticklabels(country_labels)
ax2.set_xlabel('País')

# 隐藏上方X轴顶部边框,让布局更简洁
ax2.spines['top'].set_visible(False)
# ------------------------------------------------------------------

# 其他绘图设置
ax.set_ylim(y_min, y_max)
ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
plt.title('Cantidad de Tiendas por País y Ciudad')
ax.set_ylabel('Tiendas')

# 添加柱状图数值标签
for i, val in enumerate(df['Tiendas']):
    ax.text(i, val + 1, str(val), ha='center', va='bottom', fontsize=10)

plt.tight_layout()
plt.show()

关键调整说明

  • 拆分X轴为两级:下方显示城市,上方仅在对应城市组的中心位置显示一次国家名称,完全避免重复;
  • 调整城市标签的旋转角度和对齐方式,比原90度旋转更易阅读;
  • 保留原有的数值标签、Y轴整数刻度等实用设置,同时优化了图表标题和标签的语言(贴合数据中的西班牙语国家名称)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 03:45:01