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

如何在Matplotlib中创建按日期分组的双层时间X轴柱状图

复刻双X轴时间分组柱状图问题

需求说明

我想要复刻一款Excel风格的双X轴柱状图,具体要求如下:

  • X轴按3小时增量划分时间区间
  • 柱状图根据intensity数值分级着色:
    • 低强度(0 ≤ 值 ≤5):绿色(#75FF71)
    • 中强度(6 ≤ 值 <8):黄色(#FFC53D)
    • 高强度(值 ≥8):红色(#FF5C5C)
  • 双X轴设计:
    • 上方轴显示一天中的小时刻度
    • 下方轴将时间按所属日期分组显示

当前实现代码

import matplotlib as mplt
import matplotlib.pyplot as plt
from matplotlib import dates
import numpy as np
import datetime as pdt
from datetime import datetime, timedelta
import seaborn as sns

start_dt = np.datetime64('today').astype(np.datetime64)
end_dt = np.datetime64('today') + np.timedelta64(6, 'D')

x = np.arange(start_dt,
                  end_dt, np.timedelta64(180, 'm'))
x = [i.astype(datetime) for i in x]

intensity = np.random.uniform(0, 10, len(x))

y = np.ones(shape=len(x))

plt.rcParams["figure.figsize"] = [17, 1.2]
plt.rcParams["figure.autolayout"] = True
sns.set_style("whitegrid")
sns.despine(bottom = True, left = True, top = True)
fig, ax = plt.subplots()

colors = []
for i in intensity:
    if 0 <= i <= 5:
        colors.append('#75FF71')
    elif 6 <= i < 8:
        colors.append('#FFC53D')
    else:
        colors.append('#FF5C5C')

graph = sns.barplot(x=x, y=y, palette=colors, width=1.0, linewidth=0)
graph.grid(False)
graph.set(yticklabels=[])
x_tick_label = []
for val in x:
    min_ts = min(x)
    diff_days = (val - min_ts).days
    diff_hours = (val - min_ts).seconds/3600
    total = diff_days*24 + int(diff_hours)
    if val.time() == pdt.time(0,0):
        x_tick_label.append("")
    elif val.time() == pdt.time(6,0) or val.time() == pdt.time(12,0) or val.time() == pdt.time(18,0) :
        x_tick_label.append(f"{val.strftime('%-H')}:00")
    else:
        x_tick_label.append('')
graph.set(xticklabels=x_tick_label)
for ticklabel in graph.axes.get_xticklabels():
    ticklabel.set_color("#FFC53D")

ax2 = ax.axes.twiny()

ax2.spines['top'].set_position(('axes', -0.15))
ax2.spines['top'].set_visible(False)

plt.xticks(fontweight='light',ha='right', rotation=90)
plt.box(on=None)

plt.show()

当前效果问题

当前代码生成的图表仅显示了部分小时刻度,下方的日期分组轴未正确配置,无法按日期对时间区间进行分组显示,未达到预期的双X轴效果。

优化后的代码实现

import matplotlib.pyplot as plt
from matplotlib import dates
import numpy as np
from datetime import datetime, timedelta
import seaborn as sns

# 生成时间数据:今天起6天内,每3小时一个点
start_dt = np.datetime64('today').astype(datetime)
end_dt = start_dt + timedelta(days=6)
x = np.arange(start_dt, end_dt, timedelta(hours=3)).tolist()

# 生成随机强度数据
intensity = np.random.uniform(0, 10, len(x))

# 定义颜色映射
colors = ['#75FF71' if 0 <= val <=5 else '#FFC53D' if 6 <= val <8 else '#FF5C5C' for val in intensity]

# 配置图表样式
plt.rcParams["figure.figsize"] = [17, 2]
plt.rcParams["figure.autolayout"] = True
sns.set_style("white")
fig, ax = plt.subplots()

# 绘制柱状图
sns.barplot(x=x, y=np.ones(len(x)), palette=colors, width=1.0, linewidth=0, ax=ax)

# 隐藏Y轴
ax.set_yticks([])
ax.yaxis.set_visible(False)
ax.grid(False)

# 配置上方小时轴(主X轴)
ax.set_xticks(x)
ax.set_xticklabels([dt.strftime('%H:00') if dt.hour in [0,6,12,18] else '' for dt in x], color='#FFC53D')
ax.tick_params(axis='x', length=0)

# 配置下方日期轴(副X轴)
ax2 = ax.twiny()
# 设置副轴位置在主X轴下方
ax2.spines['bottom'].set_position(('axes', -0.2))
ax2.spines['bottom'].set_visible(True)
ax2.spines['top'].set_visible(False)

# 获取每天的起始索引,计算日期刻度位置(对应每天的中间位置)
date_groups = {}
for idx, dt in enumerate(x):
    date_key = dt.date()
    if date_key not in date_groups:
        date_groups[date_key] = []
    date_groups[date_key].append(idx)

# 生成日期刻度的位置和标签
tick_positions = []
tick_labels = []
for date, indices in date_groups.items():
    # 取当天区间的中间位置作为刻度点
    mid_pos = (indices[0] + indices[-1]) / 2
    tick_positions.append(mid_pos)
    tick_labels.append(date.strftime('%m/%d'))

ax2.set_xticks(tick_positions)
ax2.set_xticklabels(tick_labels, rotation=90, ha='center', fontweight='light')
ax2.tick_params(axis='x', length=0)

# 隐藏多余边框
sns.despine(left=True, top=True, right=True)

plt.show()

关键优化点

  1. 日期轴配置:通过分组统计每天的时间点索引,将日期刻度放在当天时间段的中间位置,实现按日期分组的效果
  2. 小时轴优化:显示0、6、12、18点的刻度,其余时间点留空,保持界面简洁
  3. 轴位置调整:将日期轴移到小时轴下方,贴合需求的双轴布局
  4. 颜色映射简化:用列表推导式替代循环,代码更简洁高效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:10:23