为啥在同一数据上表达 line 和 graph_objects 散点图不同的日期?

Posted

技术标签:

【中文标题】为啥在同一数据上表达 line 和 graph_objects 散点图不同的日期?【英文标题】:Why express line and graph_objects scatter plot different dates on the same data?为什么在同一数据上表达 line 和 graph_objects 散点图不同的日期? 【发布时间】:2022-01-23 18:53:28 【问题描述】:

资助日期与学科的相同数据集使用 plotly.express (px) 线和 plotly.graph_objects (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]

删除 stackgroup 生成了相同形状的图,但错误的结束日期仍然是 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()

【问题讨论】:

如果您不使用填充区域图并从跟踪中删除参数stackgroup='one',会发生什么情况?这可以帮助您更好地直接比较图 @DerekO 我删除了 stackgroup='one',图的形状或多或少相同,但错误的结束日期仍然是 1988 年而不是 2026 年。 这很奇怪。我注意到df_fig 中有 4 个重复的日期。当你第二次下降时会是什么样子?如果您绘制,例如您的 df_fig 的一半,这个问题是否仍然存在?如果只绘制前 100 个点怎么办?如果您的 df 的一小部分仍然存在相同的问题,那么您可以将其粘贴到问题中,我们可以直接帮助您调试导致此问题的任何原因 4 个重复的日期对应于 4 个 main_disciplines。我提取了头部 20 行(在描述中添加)。感谢您的帮助。 【参考方案1】:

发生这种情况是因为您无意中将不同的数据传递给 go.Scatterpx.line。在下面的代码 sn-p 中,您传递了 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()

【讨论】:

谢谢德里克!你今晚拯救了我的睡眠:-) @Peng 没问题!我知道当没有错误但结果没有意义时会多么令人沮丧……这绝对感觉就像是如果 Plotly 抛出了ValueError: all arguments should have the same length,它会更容易弄清楚发生了什么:P【参考方案2】: 您刚刚共享了一个日期列表,创建了一个包含所有必需列的数据框 重构 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()

【讨论】:

谢谢罗伯。我看到了 scattergl 与 scatter 的区别。但是我这里的主要问题是 date_list 从 2026 年 7 月到 1988 年 3 月被 go plot 缩短了。数据是相同的,地块的形状是相同的,很困惑......

以上是关于为啥在同一数据上表达 line 和 graph_objects 散点图不同的日期?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 React Native 操作符在调试和发布版本上表现不同

为啥我的 TextInput 字段在不同的屏幕上表现不同。在本机反应

联邦学习应用思考:需求还是方法?

javaweb编程思想

在同一张图表上将 Pandas DataFrame 绘制为 Bar 和 Line

如何防止过拟合