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

求助:Matplotlib绘制含分:秒:毫秒Y轴的闪电时间差柱状图

解决Matplotlib柱状图Y轴时间差(分钟:秒:毫秒)显示异常问题

问题背景

我有7个风暴的云内闪电(IC)与云地闪电(GC)的时间差数据,需要绘制X轴为风暴编号、Y轴为「分钟:秒:毫秒」格式的柱状图,但当前代码的Y轴分钟全部显示为0,无法正确展示时间差。

原始数据

Storms (1 2 3 4 5 6 7)
time (00:00:00:131.73, 00:00:00:87.57, 00:03:23, 00:00:00:17.13, 00:08:23, 00:07:51, 00:40:41)

现有代码

import matplotlib.pyplot as plt
import matplotlib.dates as dates
from datetime import datetime, timedelta

x = ['1','2','3','4','5','6','7']
y = [00131.73, 087.57, 323, 1713, 823, 751, 4041]

fig, ax = plt.subplots(figsize=(8, 5))
plt.gca().yaxis.set_major_formatter(dates.DateFormatter('%M:%S.%f'))
plt.bar(x, y)
ax.set_title('a) Diferença de tempo entre o primeiro relâmpago IN e NS', fontsize=18)
ax.set_ylabel('Tempo (minutos)', fontsize=14)
ax.set_xlabel('Tempestades', fontsize=14)
plt.gcf().autofmt_xdate()
plt.show()

当前问题

Y轴所有刻度的分钟数均显示为0,无法正确反映实际时间差。


问题原因分析

  1. 数据格式错误:原代码中y的数值是对时间的错误转换(如把00:03:23转成323),既不是总秒数也不是datetime可识别的数值;dates.DateFormatter是用于格式化日期时间对象,而非纯数字时间差,直接使用会导致解析异常。
  2. 时间字符串格式不统一:原始时间数据存在两种格式,一种是包含毫秒的00:00:00:131.73(多余冒号导致无法直接解析),另一种是00:03:23(分:秒格式)。

解决方案

步骤1:统一解析时间字符串为总秒数

针对两种时间格式分别处理,将所有时间转换为总秒数,确保Y轴数值为连续的数值类型。

步骤2:自定义Y轴格式化器

使用FuncFormatter自定义格式化函数,将总秒数转换为「分钟:秒:毫秒」的格式,替代原有的dates.DateFormatter。


完整修正代码

import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
from datetime import timedelta

# 原始数据
storm_ids = ['1', '2', '3', '4', '5', '6', '7']
time_strings = [
    '00:00:00:131.73', 
    '00:00:00:87.57', 
    '00:03:23', 
    '00:00:00:17.13', 
    '00:08:23', 
    '00:07:51', 
    '00:40:41'
]

# 解析时间字符串为总秒数
def parse_time(s):
    if s.count(':') == 3:
        # 处理带毫秒的格式:拆分小时、分、秒、毫秒
        parts = s.split(':')
        hours = int(parts[0])
        mins = int(parts[1])
        secs = int(parts[2])
        ms = float(parts[3])
        total_secs = hours*3600 + mins*60 + secs + ms/1000
    else:
        # 处理分:秒格式
        parts = s.split(':')
        hours = int(parts[0])
        mins = int(parts[1])
        secs = int(parts[2])
        total_secs = hours*3600 + mins*60 + secs
    return total_secs

y_values = [parse_time(t) for t in time_strings]

# 自定义Y轴格式化函数:将总秒数转为「分钟:秒:毫秒」格式
def format_time(secs, pos):
    td = timedelta(seconds=secs)
    total_seconds = int(td.total_seconds())
    mins = total_seconds // 60
    secs_remaining = total_seconds % 60
    ms = int(td.microseconds // 1000)
    return f"{mins:02d}:{secs_remaining:02d}:{ms:03d}"

# 绘制柱状图
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(storm_ids, y_values)

# 设置Y轴格式化器
ax.yaxis.set_major_formatter(FuncFormatter(format_time))

# 设置标题和标签
ax.set_title('a) Diferença de tempo entre o primeiro relâmpago IN e NS', fontsize=18)
ax.set_ylabel('Tempo (minutos:segundos:milissegundos)', fontsize=14)
ax.set_xlabel('Tempestades', fontsize=14)

plt.tight_layout()
plt.show()

关键修正点说明

  • 数据解析:针对两种时间格式分别处理,将所有时间转换为总秒数,确保Y轴数值符合Matplotlib的数值要求。
  • 自定义格式化器:通过FuncFormatter实现灵活的时间格式转换,准确展示「两位分钟:两位秒:三位毫秒」的时间差。
  • 移除无效代码:删除了不适用的dates.DateFormatter和autofmt_xdate(后者用于日期X轴旋转,此处X轴为风暴编号,无需使用)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:31:00