为什么在同一数据上表达线和 graph_objects 散点图不同的日期?

Why express line and graph_objects scatter plot different dates on the same data?

使用 plotly.express (px) 线和 plotly.graph_objects (go) 散点图绘制不同的资助日期与学科的相同数据集。图的形状看起来相同,但 go 跟踪中的日期是错误的。关于这里可能有什么问题的任何建议?谢谢。

使用px.line:

fig = px.line(df_fig, x='date_list', y='monthly_avg', color='main_discipline')

使用go.Figure

plot = go.Figure()
  
plot.add_trace(go.Scatter(
    name = 'Data 1',
    x = df_fig.date_list,
    y = df_fig[df_fig.main_discipline==1].monthly_avg,
    stackgroup='one'
   ))
plot.add_trace(go.Scatter(
    name = 'Data 2',
    x = df_fig.date_list,
    y = df_fig[df_fig.main_discipline==2].monthly_avg,
    stackgroup='one'
   ))
plot.add_trace(go.Scatter(
    name = 'Data 3',
    x = df_fig.date_list,
    y = df_fig[df_fig.main_discipline==3].monthly_avg,
    stackgroup='one'
   ))
plot.add_trace(go.Scatter(
    name = 'Data 5',
    x = df_fig.date_list,
    y = df_fig[df_fig.main_discipline==5].monthly_avg,
    stackgroup='one'
   ))

date_list 的类型为 datetime64:

df_fig.date_list

0      1975-06-01
1      1975-06-01
2      1975-06-01
3      1975-06-01
4      1975-07-01
          ...    
2455   2026-07-01
2456   2026-08-01
2457   2026-08-01
2458   2026-08-01
2459   2026-08-01
Name: date_list, Length: 2460, dtype: datetime64[ns]

删除堆栈组生成了相同形状的图,但错误的结束日期仍然是 1988 年 3 月,而不是 2026 年 7 月。

这是前 20 行的数据框,日期问题持续存在

df_fig[['date_list', 'main_discipline', 'monthly_avg']]
date_list   main_discipline monthly_avg
0   1975-06-01  1   0.000000
1   1975-06-01  2   15494.000000
2   1975-06-01  3   0.000000
3   1975-06-01  5   0.000000
4   1975-07-01  1   0.000000
5   1975-07-01  2   16827.333333
6   1975-07-01  3   0.000000
7   1975-07-01  5   0.000000
8   1975-08-01  1   3880.252381
9   1975-08-01  2   16827.333333
10  1975-08-01  3   0.000000
11  1975-08-01  5   0.000000
12  1975-09-01  1   3880.252381
13  1975-09-01  2   16827.333333
14  1975-09-01  3   0.000000
15  1975-09-01  5   0.000000
16  1975-10-01  1   201134.985609
17  1975-10-01  2   986805.179029
18  1975-10-01  3   590159.728836
19  1975-10-01  5   0.000000

使用px.line

fig = px.line(df_fig[df_fig.main_discipline==1], x='date_list', y='monthly_avg')
fig.show()

使用go.Scatter

plot = go.Figure()
plot.add_trace(go.Scatter(
    name = 'Data 1',
    x = df_fig.date_list,
    y = df_fig[df_fig.main_discipline==1].monthly_avg,
))
plot.show()

  • 您刚刚共享了一个日期列表,创建了一个包含所有必需列的数据框
  • 重构 go 的使用以减少重复性
  • 从根本上说,您是通过设置 stackgroup
  • 来请求不同的格式
  • px 将使用 scattergl 用于非常大的绘图,这不支持 stackgroup。因此,更新轨迹无法使 px 绘图类似于 go 大日期范围绘图
import numpy as np
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd

ed = "1-aug-2026"
ed = "1-aug-1976"
df_fig = pd.DataFrame({"date_list": pd.date_range("1-jun-1975", ed)}).assign(
    main_discipline=lambda d: ((d.index % 5) + 1).astype(str),
    monthly_avg=lambda d: np.geomspace(1, 5 * 10 ** 7, len(d)) * d["main_discipline"].astype(int),
)

fig = px.line(df_fig, x='date_list', y='monthly_avg', color='main_discipline')
fig.show()
try:
    fig.for_each_trace(lambda t: t.update(stackgroup="one"))
except ValueError:
    print(f"{fig.data[0].type} doesn't support stackgroup")
    
fig.show()

plot = go.Figure()
for k, d in df_fig.groupby("main_discipline"):
    plot.add_trace(go.Scatter(name="Data "+k, x=d["date_list"], y=d["monthly_avg"], stackgroup="one"))

plot.show()
plot.update_traces(stackgroup=None).show()

发生这种情况是因为您无意中将不同的数据传递给 go.Scatterpx.line。在下面的代码片段中,您传递的 x=df_fig.date_list 是所有 date_list 值,但只是 monthly_avg 的一部分(由 main_discipline==1 子集)。

plot = go.Figure()
plot.add_trace(go.Scatter(
    name = 'Data 1',
    x = df_fig.date_list,
    y = df_fig[df_fig.main_discipline==1].monthly_avg,
))
plot.show()

对于这种情况,Plotly 可能会抛出 ValueError: all arguments should have the same length,而是尝试通过缩短传递给 x 的数组来匹配传递给 y 的数组来绘制它。 df_fig[df_fig.main_discipline==1].monthly_avg的长度为5,df_fig.date_list的前5个值如下:

>>> df_fig.date_list
0    1975-06-01
1    1975-06-01
2    1975-06-01
3    1975-06-01
4    1975-07-01

这解释了你得到的情节,但这绝对不是你想要的,而是应该给你正确的结果:

plot = go.Figure()
plot.add_trace(go.Scatter(
    name = 'Data 1',
    x = df_fig[df_fig.main_discipline==1].date_list,
    y = df_fig[df_fig.main_discipline==1].monthly_avg,
))
plot.show()