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

Matplotlib X轴时间戳绘制异常问题:刻度不匹配、显示数量错误

Matplotlib X轴时间戳绘制异常问题:刻度不匹配、显示数量错误

我仔细分析了你的问题和代码,发现核心问题是Matplotlib默认的自动刻度逻辑覆盖了你手动设置的刻度,同时你的刻度范围没有完全匹配数据的时间跨度,导致出现刻度数量不足、错位的问题。下面是具体的诊断和修复方案:


问题诊断

  1. 你已经正确计算了11个符合要求的刻度点(x_positions和x_labels),但Matplotlib的AutoLocator组件会自动过滤它认为“冗余”的刻度,最终只显示8个左右。
  2. 你的x_positions计算没有确保覆盖整个时间轴的最大范围,导致Matplotlib自动补充额外刻度,破坏了你的手动设置。

修复方案(分步骤)

1. 强制Matplotlib使用你的手动刻度

替换原来的plt.xticks(...)代码,显式关闭自动刻度调整,强制使用你计算的所有刻度:

# 替换原来的plt.xticks(...)部分
ax = plt.gca()
# 强制设置主刻度为你的手动计算位置
ax.set_xticks(x_positions)
# 设置刻度标签
ax.set_xticklabels(x_labels, rotation=45, ha='right')
# 关闭Matplotlib的自动主刻度生成器
ax.xaxis.set_major_locator(plt.FixedLocator(x_positions))
# 可选:关闭次要刻度,避免干扰
ax.xaxis.set_minor_locator(plt.NullLocator())

这一步会完全禁用Matplotlib的自动刻度逻辑,确保你设置的10-12个刻度全部显示。

2. 修正刻度范围与数量控制

调整你的x_positions和dif计算逻辑,确保:

  • 刻度数量稳定在10-12之间
  • 最后一个刻度刚好对应数据的最后一个时间点(覆盖整个时间轴)

修改dif计算和刻度收集的代码:

# 修正dif计算:确保生成10-12个刻度
total_data_points = len(df)
# 计算初始dif:(总点数 +9)//10 确保至少生成10个刻度
dif = max(1, (total_data_points + 9) // 10)

# 收集刻度:确保覆盖整个时间范围
x_labels = []
x_positions = []
# 按dif步长取点
for i in range(0, total_data_points, dif):
    time = df['Time'].iloc[i]
    x_labels.append(time.strftime('%H:%M:%S'))
    x_positions.append((time - min(df['Time'])).total_seconds() / 60)

# 检查最后一个刻度是否是数据的最后一个时间点,如果不是则添加
last_time_diff = df['Time_diff'].iloc[-1]
if abs(x_positions[-1] - last_time_diff) > 0.01:  # 避免浮点误差
    last_time = df['Time'].iloc[-1]
    x_labels.append(last_time.strftime('%H:%M:%S'))
    x_positions.append(last_time_diff)

# 确保刻度数量不超过12,若超过则增大dif重新计算
while len(x_positions) > 12:
    dif +=1
    x_labels = []
    x_positions = []
    for i in range(0, total_data_points, dif):
        time = df['Time'].iloc[i]
        x_labels.append(time.strftime('%H:%M:%S'))
        x_positions.append((time - min(df['Time'])).total_seconds() /60)
    # 再次检查是否需要添加最后一个点
    if abs(x_positions[-1] - last_time_diff) >0.01:
        last_time = df['Time'].iloc[-1]
        x_labels.append(last_time.strftime('%H:%M:%S'))
        x_positions.append(last_time_diff)

3. 统一时间差计算逻辑

确保绘图用的Time_diff和刻度用的x_positions计算逻辑完全一致,避免浮点差异导致的错位:

# 统一计算时间差(以第一个CSV的最早时间为基准)
base_time = df['Time'].min()
df_addr['Time_diff'] = (df_addr['Time'] - base_time).total_seconds() /60

修改后的完整plot_data函数

这里是整合所有修复后的plot_data函数,你可以直接替换原代码:

def plot_data(data):
    plt.figure(figsize=(14, 8))
    colors = generate_colors(len(data))

    # 取第一个DataFrame作为时间基准(假设所有CSV时间范围一致)
    df_base = next(iter(data.values()))
    total_data_points = len(df_base)
    base_time = df_base['Time'].min()
    last_time_diff = (df_base['Time'].iloc[-1] - base_time).total_seconds() /60

    # 计算初始dif:确保生成10-12个刻度
    dif = max(1, (total_data_points + 9) // 10)

    # 收集x轴刻度:确保覆盖整个时间范围
    x_labels = []
    x_positions = []
    for i in range(0, total_data_points, dif):
        time = df_base['Time'].iloc[i]
        x_labels.append(time.strftime('%H:%M:%S'))
        x_positions.append((time - base_time).total_seconds() /60)
    
    # 添加最后一个时间点(如果未包含)
    if abs(x_positions[-1] - last_time_diff) > 0.01:
        last_time = df_base['Time'].iloc[-1]
        x_labels.append(last_time.strftime('%H:%M:%S'))
        x_positions.append(last_time_diff)
    
    # 确保刻度数量不超过12
    while len(x_positions) >12:
        dif +=1
        x_labels = []
        x_positions = []
        for i in range(0, total_data_points, dif):
            time = df_base['Time'].iloc[i]
            x_labels.append(time.strftime('%H:%M:%S'))
            x_positions.append((time - base_time).total_seconds()/60)
        if abs(x_positions[-1] - last_time_diff) >0.01:
            last_time = df_base['Time'].iloc[-1]
            x_labels.append(last_time.strftime('%H:%M:%S'))
            x_positions.append(last_time_diff)

    # 绘制所有地址的Ping数据
    for idx, (address, df_addr) in enumerate(data.items()):
        # 统一计算时间差(基于基准时间)
        df_addr['Time_diff'] = (df_addr['Time'] - base_time).total_seconds() /60
        mask_timeout = df_addr['Ping (ms)'] ==0
        mask_normal = ~mask_timeout

        plt.plot(df_addr['Time_diff'][mask_normal], df_addr['Ping (ms)'][mask_normal], 
                 label=address, color=colors[idx % len(colors)])
        plt.plot(df_addr['Time_diff'][mask_timeout], df_addr['Ping (ms)'][mask_timeout], 
                 color='r', lw=2)

    # 配置X轴(核心修复)
    ax = plt.gca()
    ax.set_xticks(x_positions)
    ax.set_xticklabels(x_labels, rotation=45, ha='right')
    ax.xaxis.set_major_locator(plt.FixedLocator(x_positions))
    ax.xaxis.set_minor_locator(plt.NullLocator())

    # 其他绘图配置
    plt.xlabel('Time')
    plt.ylabel('Ping (ms)')
    plt.title('Ping Times for Different Addresses')
    plt.legend()
    plt.grid(True)
    plt.tight_layout()
    plt.show()

测试效果

用你提供的99条数据测试,这个代码会生成11个刻度点,全部正确显示在X轴上,且每个刻度都对应你计算的时间戳,不会出现错位或数量不足的问题。


备注:内容来源于stack exchange,提问作者Pantastix

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 16:04:34