Plotly:在 python 中添加时间序列趋势层

Plotly: Add Time Series Trend layer in python

我是 python 的新手,想知道 Python 中是否有类似 geom_smooth 的 R。目前,我有一个具有不同分布的月度时间序列箱形图:

我想在箱形图上添加一条平滑的范围曲线,使其看起来像 R:

中的粉红色 geom_smooth 趋势线

这是我用来创建绘图箱线图的代码:

import pandas as pd
import numpy as np

df = pd.DataFrame()

df['date'] = pd.date_range('2021-01-01', '2021-12-20', freq='D')
df['month'] = df['date'].dt.month
df['spot_rate'] = np.random.randint(low=150, high=400, size=len(df.index))
            
fig2 = px.box(df, x="month", y="spot_rate")
fig2.show()

您可以计算每个箱线图的中位数 y_bar,并通过使用参数 line_shape="spline".

调用 go.Scatter 来绘制平滑的蓝色趋势线

如果您希望趋势线通过每个箱线图的均值而不是中值,那么您可以使用:

trendline = df.groupby(['month']).spot_rate.mean()

然后您可以使用 y_bar ± 1.96*stds/np.sqrt(n_vals)) 计算 95% 置信区间应该经过的点,其中 y_bar 是每个月的中位数,stds 是每个月的标准差,并且n_vals 是每个月的数据点数。

然后通过较高置信区间的数组绘制样条,然后通过较低置信区间绘制样条并填充两条线之间的区域(类似于 Plotly 文档的 "Filled Lines" section)。

编辑:要在 x 轴上显示所有月份,您可以将 tickmode 设置为数组,并且 tickvals=x1。

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

df = pd.DataFrame()

df['date'] = pd.date_range('2021-01-01', '2021-12-20', freq='D')
df['month'] = df['date'].dt.month

## set seed for reproducibility
np.random.seed(42)
df['spot_rate'] = np.random.randint(low=150, high=400, size=len(df.index))

fig = px.box(df, x="month", y="spot_rate")

trendline = df.groupby(['month']).spot_rate.mean()
x1,y1 = list(trendline.index), trendline.values
stds = df.groupby(['month']).spot_rate.std().values
n_vals = df.groupby(['month']).date.count().values

## construct a 0.95 CI using mean ± z*std/sqrt(n)
y1_upper = list(y1 + 1.96*stds/np.sqrt(n_vals))
y1_lower = list(y1 - 1.96*stds/np.sqrt(n_vals))
y1_lower = y1_lower[::-1]

x1_rev = x1[::-1]

fig.add_trace(go.Scatter(x=x1, y=y1, line_shape="spline", line_color="blue", name="trendline"))

fig.add_trace(go.Scatter(
    x=x1+x1_rev,
    y=y1_upper+y1_lower,
    line_shape="spline",
    fill='toself',
    fillcolor='rgba(255,192,203,0.5)',
    line_color='rgba(255,255,255,0)',
    showlegend=False,
    name="0.95 CI",
))

fig.update_layout(xaxis = dict(tickmode='array', tickvals=x1))

fig.show()