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

如何实现24小时轴自定义排序绘制每日数据(12:00-11:59)

实现从12:00到次日11:59的24小时轴绘图

问题说明

应用自定义排序函数custom_date_sorter后,绘图x轴未按预期从12:00:00开始到次日11:59:59显示,需确保数据与时间正确对应,不能仅偏移时间而不调整数据关联。

解决方案

核心思路是重新计算时间戳的基准(以12:00为当日起点),并调整x轴刻度与标签的映射:

  • 重新计算时间秒数:将每个时间点转换为以当日12:00为起点的秒数,早于12:00的时间自动加上24小时秒数,实现12:00到次日11:59的区间映射
  • 调整x轴刻度标签:生成从12:00开始的24小时标签,对应新的秒数刻度
  • 保留原有排序逻辑:确保数据按自定义规则排序后,绘图时使用新的秒数列作为x轴

修改后的完整代码

import random
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.ticker as tkr
from datetime import time as dtime
random.seed(0)

df = pd.DataFrame({'DATE_TIME': pd.date_range('2022-11-01', '2022-11-06 23:00:00', freq='20min'),
                   'ID': [random.randrange(1, 3) for n in range(430)]})
df['VALUE1'] = [random.uniform(110, 160) for n in range(430)]
df['VALUE2'] = [random.uniform(50, 80) for n in range(430)]
df['INSPECTION'] = df['DATE_TIME'].dt.day

df['MODE'] = np.select([df['INSPECTION'] == 1, df['INSPECTION'].isin([2, 3])], ['A', 'B'], 'C')
df['TIME'] = df['DATE_TIME'].dt.time.astype('str')

df['TIMEINTERVAL'] = df.DATE_TIME.diff().astype('timedelta64[m]').fillna(0)

def to_day_period(s):
    bins = ['0', '06:00:00', '13:00:00', '18:00:00', '23:00:00', '24:00:00']
    labels = ['Nighttime', 'Daytime', 'Daytime', 'Nighttime', 'Nighttime']
    return pd.cut(
        pd.to_timedelta(s),
        bins=list(map(pd.Timedelta, bins)),
        labels=labels, right=False, ordered=False
    )

df['TIME_OF_DAY'] = to_day_period(df['TIME'])

# 筛选目标数据
df = df[(df['ID'] == 1) & (df['INSPECTION'].isin([1, 2, 3]))]

# 自定义排序函数:按12小时偏移后的时间排序
def custom_date_sorter(s):
    s = pd.to_datetime(s)
    return np.argsort(np.lexsort([s.sub(pd.Timedelta('12h')).dt.time,
                                  s.dt.normalize()]))

df = df.sort_values(by='DATE_TIME', key=custom_date_sorter)

# 计算以当日12:00为起点的秒数
def get_seconds_from_noon(dt):
    noon = dt.replace(hour=12, minute=0, second=0, microsecond=0)
    delta = dt - noon
    return delta.total_seconds() if delta.total_seconds() >=0 else delta.total_seconds() + 24*3600

df['seconds_from_noon'] = df['DATE_TIME'].apply(get_seconds_from_noon)

sns.set_style('darkgrid')
sns.set(rc={'figure.figsize':(14,8)})

# 循环绘图
for id_ in sorted(df.ID.unique()):
    data = df[df.ID.eq(id_)]
    fig = plt.figure(figsize=(10, 6))
    ax = sns.lineplot(data=data, x='seconds_from_noon', y='VALUE1', hue='INSPECTION', palette='viridis', legend='full')
    
    ax.set(title=f'ID: {id_}', xlabel='TIME', ylabel='VALUE1')
    sns.move_legend(ax, bbox_to_anchor=(1.0, 0.5), loc='center left', frameon=False)
    
    # 设置x轴范围:0秒(12:00)到43200秒(次日12:00,对应11:59的结束区间)
    ax.set_xlim(0, 24*3600)
    
    # 生成12:00到次日11:00的小时标签
    hour_labels = [f"{h:02d}:00" for h in list(range(12,24)) + list(range(0,12))]
    
    # 每小时设置一个刻度,对应从12:00开始的秒数
    ax.xaxis.set_major_locator(tkr.MultipleLocator(3600))
    ax.set_xticks(ticks=np.arange(0, 24*3600+1, 3600), labels=hour_labels, rotation=90)
    
    ax.spines[['top', 'right']].set_visible(False)

plt.show()

关键改动说明

  • seconds_from_noon列:将每个时间点转换为相对于当日12:00的秒数,早于12:00的时间自动加上24小时秒数,实现时间区间的循环偏移
  • x轴标签与刻度:生成从12:00到次日11:00的24个小时标签,对应0到43200秒的刻度位置,完美匹配需求的时间轴范围
  • 排序逻辑保留:原自定义排序函数确保数据按12小时偏移后的顺序排列,绘图时使用新的秒数列,保证数据点在x轴上的位置与时间逻辑完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:44:56