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

Pandas DataFrame中时间轴多循环异常问题排查

问题分析与解决方案

这不是Plotly的bug,而是Plotly对分组(color参数)数据的默认渲染逻辑导致的:当你按short_symbol分组时,Plotly会为每个分组单独处理x轴数据的显示顺序,而非使用全局统一的时间排序刻度。当不同分组的时间数据覆盖范围不同时,就会出现x轴重复循环的现象。

核心原因

  • 不设置color时,Plotly基于全局数据的排序结果生成x轴刻度,因此time_of_day_num呈现单调递增;
  • 设置color后,每个short_symbol分组会保留自身数据的顺序,Plotly会依次渲染每个分组的x轴刻度,最终导致多个循环叠加。

解决方案

方案1:使用数值型时间(time_of_day_num)作为x轴,自定义刻度显示为时间格式

直接用已计算的time_of_day_num作为x轴,手动将刻度标签替换为对应的时间字符串,既保证x轴单调递增,又能显示友好的时间格式:

import plotly.express as px

# 保留原有的数据处理步骤
df['time_of_day'] = df['entrydate'].dt.time
df['time_of_day_num'] = df['time_of_day'].apply(lambda x: x.hour * 3600 + x.minute * 60 + x.second)
df.sort_values(by='time_of_day_num', inplace=True)

# 获取唯一的时间数值和对应的时间字符串,用于自定义刻度
unique_times = df.drop_duplicates('time_of_day_num').sort_values('time_of_day_num')
tick_vals = unique_times['time_of_day_num'].tolist()
tick_texts = [t.strftime('%H:%M:%S') for t in unique_times['time_of_day'].tolist()]

# 绘图,x用数值型时间,自定义刻度
fig = px.scatter(df, x='time_of_day_num', y='realizedpnl', color='short_symbol', hover_data=['entrydate','realizedpnl'])
fig.update_layout(
    xaxis=dict(
        tickmode='array',
        tickvals=tick_vals,
        ticktext=tick_texts,
        title='Time of Day'
    )
)
fig.show()

方案2:将time_of_day转换为可排序的字符串类型

把datetime.time类型转为%H:%M:%S格式的字符串,Plotly会基于字符串的字典序(对应时间顺序)生成全局统一的x轴刻度:

import plotly.express as px

df['time_of_day_str'] = df['entrydate'].dt.strftime('%H:%M:%S')
df.sort_values(by='time_of_day_str', inplace=True)

fig = px.scatter(df, x='time_of_day_str', y='realizedpnl', color='short_symbol', hover_data=['entrydate','realizedpnl'])
fig.show()

方案3:使用Plotly Graph Objects手动构建图表(更灵活)

手动创建每个分组的trace,统一设置x轴的全局刻度,完全控制渲染逻辑:

import plotly.graph_objects as go

# 数据处理
df['time_of_day'] = df['entrydate'].dt.time
df['time_of_day_num'] = df['time_of_day'].apply(lambda x: x.hour * 3600 + x.minute * 60 + x.second)
df.sort_values(by='time_of_day_num', inplace=True)

# 获取全局唯一的时间列表(排序后)
sorted_unique_times = df['time_of_day'].unique().tolist()
sorted_unique_times.sort()

# 创建图表
fig = go.Figure()
# 遍历每个symbol,添加trace
for symbol in df['short_symbol'].unique():
    subset = df[df['short_symbol'] == symbol]
    fig.add_trace(go.Scatter(
        x=subset['time_of_day'],
        y=subset['realizedpnl'],
        mode='markers',
        name=symbol,
        hovertext=subset.apply(lambda row: f"Entry Date: {row['entrydate']}<br>Realized PnL: {row['realizedpnl']}", axis=1)
    ))

# 设置x轴为全局排序后的时间
fig.update_layout(
    xaxis=dict(
        tickmode='array',
        tickvals=sorted_unique_times,
        title='Time of Day'
    ),
    yaxis=dict(title='Realized PnL')
)
fig.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 02:25:34