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

如何在Plotly Express中格式化timedelta对象的Y轴

问题:Plotly Express中Timedelta类型Y轴显示格式异常

在Pandas中,timedelta对象可正常显示为0 days 03:00:00这类易读格式,但使用Plotly Express绘图时,Y轴却显示为40T这类难以理解的缩写格式。尝试过将timedelta转为字符串或调整格式化参数,要么格式失效,要么无变化。需求是让Y轴显示易读的时长格式(以小时、分钟为主,超过一天的时长显示为40:xx:xx这类累计小时数的格式)。

用户原始代码如下:

import pandas as pd
data = [['tom', 10, "2023-06-21 06:23:55+00:00", "2023-06-21 09:23:55+00:00"], ['nick', 15, "2023-06-20 06:23:55+00:00", "2023-06-21 06:23:55+00:00"], ['juli', 14, "2023-06-21 06:23:50+00:00", "2023-06-21 06:23:55+00:00"]]
df = pd.DataFrame(data, columns=['name', 'age', "start", "stop"])
df["start"] = pd.to_datetime(df["start"])
df["stop"] = pd.to_datetime(df["stop"])
df["duration"] = df["stop"] - df["start"]
df["duration"]

#### output
0   0 days 03:00:00
1   1 days 00:00:00
2   0 days 00:00:05
Name: duration, dtype: timedelta64[ns]

import plotly.express as px
import plotly.graph_objects as go

fig = px.scatter(
        df,
        x=df["age"].sort_values(ascending=False),
        y="duration", # 推测显示的是秒数
        #y=pd.to_timedelta(df.duration, unit='h'), # 格式与之前一致
        #y=df["duration"].sort_values(ascending=True).dt.to_pytimedelta().astype(str), # 标签固定,但刻度间距与数值差无关
        color="name",
    )
figure = go.Figure(data=fig)
# figure.update_layout(yaxis_tickformat='%H:%M:%S') # 会添加大量零
# figure.update_layout(yaxis_tickformat="%H:%M:%S.%f")
figure.show()

当前Y轴显示异常效果:
Plotly Y轴异常显示


解决方案

核心思路是将timedelta转换为总秒数作为绘图的数值轴(保证刻度间距逻辑正确),再自定义函数将秒数格式化为易读的时长格式,最后手动替换Y轴的刻度标签。

完整修改后代码:

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

# 数据处理
data = [['tom', 10, "2023-06-21 06:23:55+00:00", "2023-06-21 09:23:55+00:00"], 
        ['nick', 15, "2023-06-20 06:23:55+00:00", "2023-06-21 06:23:55+00:00"], 
        ['juli', 14, "2023-06-21 06:23:50+00:00", "2023-06-21 06:23:55+00:00"]]
df = pd.DataFrame(data, columns=['name', 'age', "start", "stop"])
df["start"] = pd.to_datetime(df["start"])
df["stop"] = pd.to_datetime(df["stop"])
df["duration"] = df["stop"] - df["start"]
# 将timedelta转换为总秒数,用于维持轴的数值逻辑
df["duration_sec"] = df["duration"].dt.total_seconds()

# 自定义时长格式化函数:将秒数转为 小时:分钟:秒 格式,小时数累计(含跨天)
def format_timedelta(seconds):
    hours = int(seconds // 3600)
    minutes = int((seconds % 3600) // 60)
    secs = int(seconds % 60)
    return f"{hours}:{minutes:02d}:{secs:02d}"

# 绘制散点图,使用总秒数作为Y轴数值
fig = px.scatter(
    df,
    x=df["age"].sort_values(ascending=False),
    y="duration_sec",
    color="name",
    # 自定义hover信息,保留原始timedelta格式提升可读性
    hover_data={"duration_sec": False, "duration": True}
)

# 获取默认的Y轴刻度值,转换为自定义格式的标签
tick_vals = fig.layout.yaxis.tickvals
tick_text = [format_timedelta(val) for val in tick_vals]

# 更新Y轴设置,替换刻度标签
fig.update_layout(
    yaxis=dict(
        tickmode='array',
        tickvals=tick_vals,
        ticktext=tick_text,
        title="时长"
    )
)

fig.show()

关键说明

  • 转换为总秒数:避免直接使用字符串类型导致Y轴刻度间距混乱,保证轴的数值逻辑正确(比如1天的时长会被识别为86400秒,和3小时的10800秒保持正确比例)
  • 自定义格式化函数:自动累计小时数,跨天时长会显示为24:00:00而非1 days 00:00:00,符合需求中的显示格式
  • 保留hover信息:在鼠标悬浮时显示原始timedelta格式,兼顾轴的简洁性和数据的完整性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 07:37:11