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

解决Matplotlib股票图表非交易时段时间间隔空白问题

解决股票Streamlit仪表盘图表非交易时段空白连线问题

我正在搭建股票市场的Streamlit仪表盘,股票数据仅包含每日9:00至16:00的交易时段数据。用mdates设置X轴刻度后,图表出现16:00到次日9:00的空白连线(非交易时段无数据却被强制连线),尝试过滤数据无效,附上代码和示例截图,求解决方法。

def create_plot(name:str,label:str,title_info:str,data,period_var:str):
        fig, ax1 = plt.subplots(figsize=(16,8))

        ax1.set_ylabel(name)
        plt.xlabel('Datetime')
        plt.ylabel(label)
        plt.title(title_info)
        
        if period_var in ["1d"]:
            date_formatter = DateFormatter('%H:%M')
            ax1.xaxis.set_major_formatter(date_formatter)
            ax1.xaxis.set_major_locator(mdates.MinuteLocator(interval=30))

        elif period_var in ["3d","5d"]:
            date_formatter = DateFormatter("%d-%H")
            ax1.xaxis.set_major_formatter(date_formatter)
            ax1.xaxis.set_major_locator(mdates.HourLocator(byhour=range(9,16),interval=2))
        elif period_var in ["1mo", "3mo", "6mo"]:
            date_formatter = DateFormatter("%Y - %b")
            ax1.xaxis.set_major_formatter(date_formatter)

            ax1.xaxis.set_major_locator(mdates.DayLocator(interval=int(period_var[0])*2))
        elif period_var in ["1y", "2y", "5y"]:
            date_formatter = DateFormatter("%Y-%b")
            ax1.xaxis.set_major_formatter(date_formatter)
            ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=int(period_var[0])))
        else:
            date_formatter = DateFormatter("%Y")
            ax1.xaxis.set_major_formatter(date_formatter)
            ax1.xaxis.set_major_locator(mdates.YearLocator())
            

        ax1.plot(data.Date, data[name], label=name, marker='o', markersize=1)
        plt.xticks(rotation=45)
        plt.legend()
        plt.grid(True)
        plt.tight_layout()

        return fig

非交易时段空白连线示例


核心问题

Matplotlib的plot函数默认按时间序列连续绘制,哪怕相邻数据点间隔十几个小时(非交易时段),也会直接连线,导致出现跨时段的空白线条。

解决方案

在每日收盘(16:00)和次日开盘(9:00)之间插入NaN值,让Matplotlib自动断开这些位置的连线,同时保留时间轴的刻度逻辑。

修改后的完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.dates import DateFormatter

def create_plot(name:str,label:str,title_info:str,data,period_var:str):
    # 处理非交易时段断开连线:在每日收盘后插入NaN占位行
    data['Date'] = pd.to_datetime(data['Date'])
    # 按日期分组,获取每个交易日的最后一条数据索引
    daily_last_indices = data.groupby(data['Date'].dt.date).tail(1).index
    # 创建NaN行(仅需保证Date和目标列结构匹配,其他列按需补充)
    nan_rows = pd.DataFrame({
        'Date': data.loc[daily_last_indices, 'Date'] + pd.Timedelta(hours=1),
        name: np.nan
    })
    # 合并原数据与NaN行,重新排序后绘图
    combined_data = pd.concat([data, nan_rows]).sort_values('Date').reset_index(drop=True)

    fig, ax1 = plt.subplots(figsize=(16,8))

    ax1.set_ylabel(name)
    plt.xlabel('Datetime')
    plt.ylabel(label)
    plt.title(title_info)
    
    if period_var in ["1d"]:
        date_formatter = DateFormatter('%H:%M')
        ax1.xaxis.set_major_formatter(date_formatter)
        ax1.xaxis.set_major_locator(mdates.MinuteLocator(interval=30))

    elif period_var in ["3d","5d"]:
        date_formatter = DateFormatter("%d-%H")
        ax1.xaxis.set_major_formatter(date_formatter)
        ax1.xaxis.set_major_locator(mdates.HourLocator(byhour=range(9,16),interval=2))
    elif period_var in ["1mo", "3mo", "6mo"]:
        date_formatter = DateFormatter("%Y - %b")
        ax1.xaxis.set_major_formatter(date_formatter)

        ax1.xaxis.set_major_locator(mdates.DayLocator(interval=int(period_var[0])*2))
    elif period_var in ["1y", "2y", "5y"]:
        date_formatter = DateFormatter("%Y-%b")
        ax1.xaxis.set_major_formatter(date_formatter)
        ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=int(period_var[0])))
    else:
        date_formatter = DateFormatter("%Y")
        ax1.xaxis.set_major_formatter(date_formatter)
        ax1.xaxis.set_major_locator(mdates.YearLocator())
        
    # 使用处理后的数据绘图
    ax1.plot(combined_data.Date, combined_data[name], label=name, marker='o', markersize=1)
    plt.xticks(rotation=45)
    plt.legend()
    plt.grid(True)
    plt.tight_layout()

    return fig

补充说明

  • 如果数据包含其他列,在创建nan_rows时需要同步添加对应列的NaN值,保证数据结构一致
  • 该方法既保留了时间轴的刻度逻辑,又能精准断开非交易时段的无效连线,比将X轴转为分类变量的方案更贴合股票时间序列的展示需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 23:21:28