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

如何移除Matplotlib中x轴的空坐标 解决重复名称绘图异常问题

修正后可运行代码

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

data = {'Name': ['Status', 'Status', 'HMI', 'Allst', 'Drvr', 'CurrTUBand', 'RUSource', 'RUReqstrPriority', 'RUReqstrSystem', 'RUResReqstStat', 'CurrTUBand', 'DSP', 'SetDSP', 'SetDSP', 'DSP', 'RUSource', 'RUReqstrPriority', 'RUReqstrSystem', 'RUResReqstStat', 'Status', 'Delay', 'Status', 'Delay', 'HMI', 'Status', 'Status', 'HMI', 'DSP'],
        'Value': [4, 4, 2, 1, 1, 1, 0, 7, 0, 4, 1, 1, 3, 0, 3, 0, 7, 0, 4, 1, 0, 1, 0, 1, 4, 4, 2, 3],
        'Id_Par': [0, 0, 0, 0, 0, 0, 10, 10, 10, 10, 10, 0, 0, 22, 22, 28, 28, 28, 28, 0, 0, 38, 38, 0, 0, 0, 0, 0]
}

signals_df = pd.DataFrame(data)


def plot_signals(signals_df):
    # Count signals by parallel
    signals_df['Count'] = signals_df.groupby('Id_Par').cumcount().add(1).mask(signals_df['Id_Par'].eq(0), 0)
    # Subtract Parallel values from the index column
    signals_df['Sub'] = signals_df.index - signals_df['Count']
    id_par_prev = signals_df['Id_Par'].unique()
    id_par = np.delete(id_par_prev, 0)
    signals_df['Prev'] = [1 if x in id_par else 0 for x in signals_df['Id_Par']]
    signals_df['Final'] = signals_df['Prev'] + signals_df['Sub']
    # 按计算后的Final索引排序后重置连续索引作为绘图x轴位置
    signals_df.sort_values('Final', inplace=True)
    signals_df.reset_index(drop=True, inplace=True)
    # 记录原始Final索引作为x轴刻度标签
    x_labels = signals_df['Final'].values.tolist()
    # 识别需要加黄色阴影的跳过区间
    skip_intervals = []
    current_par = None
    start_idx = None
    for idx, row in signals_df.iterrows():
        if row['Id_Par'] != 0:
            if current_par is None:
                current_par = row['Id_Par']
                start_idx = idx
        else:
            if current_par is not None:
                skip_intervals.append((start_idx-0.5, idx-0.5))
                current_par = None
    if current_par is not None:
        skip_intervals.append((start_idx-0.5, len(signals_df)-0.5))

    # Get individual names and variables for the chart
    names_list = [name for name in signals_df['Name'].unique()]
    num_names_list = len(names_list)

    # Creation Graphics
    fig, ax = plt.subplots(nrows=num_names_list, figsize=(10, 10), sharex=True)
    plt.xticks(color='SteelBlue', fontweight='bold')

    # 用连续数值作为x轴位置,手动设置刻度标签避免分类轴乱序问题
    x_pos = np.arange(len(signals_df))
    plt.xticks(x_pos, labels=[str(i) for i in x_labels])

    for pos, (a_, name) in enumerate(zip(ax, names_list)):
        # 绘制跳过区域黄色阴影
        for (start, end) in skip_intervals:
            a_.axvspan(start, end, color='yellow', alpha=0.3)
        # Get data
        data = signals_df[signals_df["Name"] == name]["Value"]
        # Get values axis-x and axis-y
        x_ = np.hstack([-1, data.index.values, len(signals_df)])
        y_ = np.hstack([0, data.values, data.iloc[-1]])
        # 直接用数值x轴绘图
        a_.plot(x_, y_, drawstyle='steps-post', marker='*', markersize=8, color='k', linewidth=2)
        a_.set_ylabel(name, fontsize=8, fontweight='bold', color='SteelBlue', rotation=30, labelpad=35)
        a_.yaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))
        a_.yaxis.set_tick_params(labelsize=6)
        a_.grid(alpha=0.4, color='SteelBlue')
        # 标注数值
        for i in range(len(y_)-1):
            xy = [x_[i], y_[i]]
            a_.text(x=xy[0], y=xy[1], s=str(xy[1]), color='k', fontweight='bold', fontsize=12)
    plt.xlim(-0.5, len(signals_df)-0.5)
    plt.tight_layout()
    plt.show()


plot_signals(signals_df)

核心改动说明

  • 修复了原代码未定义变量all_names_list的语法错误
  • 放弃将x值转为字符串的分类轴方案,改用连续数值作为x轴位置,手动映射原始Final索引作为刻度标签,彻底避免x轴值重复导致的顺序错乱
  • 新增了跳过区间的黄色阴影绘制逻辑,自动识别Id_Par非0的并行区间添加半透明黄色背景
  • 调整了x轴范围和文本标注逻辑,避免标注错位
  • 对dataframe按Final索引排序后重置了连续数值索引,避免绘图时索引跳跃导致的图形异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 13:48:03