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

如何在24小时X轴上绘制任务起止时间直方图并实现合理分箱?

问题描述

我有一个包含datetime类型数据的DataFrame,字段如下:

  • Start_time:任务开始时间戳,示例:2013-09-21 00:14:00
  • End_time:任务结束时间戳,示例:2013-09-22 11:04:00
  • Time_diff:任务耗时,示例:0 days 06:07:00

我想绘制仅按24小时制(忽略日期)统计的任务起止时间直方图,目标是X轴为24小时区间,Y轴为对应分箱内的起止时间分布数量。

尝试用df['Start_time'].dt.time提取时间后绘制直方图,但无法将这些时间对象正确划分为20个分箱。直接用原始datetime字段绘制的话,会因为日期不同导致X轴跨多天,不符合需求。

以下是我使用的代码:

from random import randrange
import datetime
import pandas as pd 
import plotly.express as px

# 生成示例数据集
startDate = datetime.datetime(2013, 9, 20,13,00)
start_lst = [] 
end_lst = []
for i in range(200):
    start_time= startDate + datetime.timedelta(hours=randrange(23), minutes= randrange(60))
    end_time  = start_time + datetime.timedelta(hours=randrange(2,7), minutes= randrange(60))
    startDate = startDate + datetime.timedelta(days=randrange(4))
    start_lst.append(start_time)
    end_lst.append(end_time)

df = pd.DataFrame({'Start_time': start_lst, 
                   'End_time':  end_lst 
                   })
df['Time_diff'] = df['End_time']-df['Start_time']

# 尝试直接绘制,但日期不同导致X轴跨多天
fig = px.histogram(df, x=['Start_time', 'End_time'], nbins=20)
fig.show()

# 尝试提取时间部分,但无法正确分箱
df['Start_time_nodate'] = df['Start_time'].dt.time
df['End_time_nodate']   = df['End_time'].dt.time
   
fig = px.histogram(df, x=['Start_time_nodate', 'End_time_nodate'], nbins=20)
fig.show()
解决方案

问题核心是dt.time返回的datetime.time对象无法被Plotly正常分箱。正确做法是将时间转换为一天内的数值型小时数,完成分箱后再将X轴标签转回时间格式。

修改后的代码如下:

from random import randrange
import datetime
import pandas as pd 
import plotly.express as px

# 生成示例数据集
startDate = datetime.datetime(2013, 9, 20,13,00)
start_lst = [] 
end_lst = []
for i in range(200):
    start_time= startDate + datetime.timedelta(hours=randrange(23), minutes= randrange(60))
    end_time  = start_time + datetime.timedelta(hours=randrange(2,7), minutes= randrange(60))
    startDate = startDate + datetime.timedelta(days=randrange(4))
    start_lst.append(start_time)
    end_lst.append(end_time)

df = pd.DataFrame({'Start_time': start_lst, 
                   'End_time':  end_lst 
                   })
df['Time_diff'] = df['End_time']-df['Start_time']

# 将时间转换为一天内的小时数(数值型,支持均匀分箱)
df['Start_hour'] = df['Start_time'].dt.hour + df['Start_time'].dt.minute/60 + df['Start_time'].dt.second/3600
df['End_hour'] = df['End_time'].dt.hour + df['End_time'].dt.minute/60 + df['End_time'].dt.second/3600

# 合并起止时间数据,方便分组绘制
melted_df = pd.melt(df, value_vars=['Start_hour', 'End_hour'], 
                    var_name='时间类型', value_name='一天中的小时数')

# 绘制20个分箱的直方图
fig = px.histogram(melted_df, x='一天中的小时数', color='时间类型', 
                   nbins=20, barmode='overlay', opacity=0.7)

# 将X轴刻度转为易读的时间格式
hour_ticks = [i for i in range(0,25,2)]
tick_labels = [f"{h:02d}:00" for h in hour_ticks]
fig.update_layout(
    xaxis=dict(
        title='一天中的时间',
        tickmode='array',
        tickvals=hour_ticks,
        ticktext=tick_labels
    ),
    yaxis_title='数量',
    title='任务起止时间24小时分布直方图'
)

fig.show()

关键说明

  1. 时间转数值:把时间转换成带小数的小时数(如1点30分对应1.5),让Plotly可以对数值进行均匀分箱。
  2. 数据融合:用pd.melt合并起止时间列,实现按“开始/结束”类型分组展示。
  3. X轴格式化:把数值刻度转回HH:00的时间格式,保证X轴符合24小时制的直观展示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:45:36