我想创建一个使用 Plotly 滑块在 20 个不同图表之间变化的图形。我正在对移动平均值进行建模,其中滑块会更改数据聚合中使用的天数。我想要可视化的第二条数据是该移动平均线的 savgol 滤波器。我正在尝试在每个图表上绘制两个单独的数据数组,但截至目前,它当前将数组附加到单独的步骤上。我希望 20 个步骤的图表具有 2 个不同的函数,而不是 40 个步骤,每个步骤只有一个函数。
我的模拟数据是:
# Imports
import pandas as pd
import numpy as np
import plotly
import plotly.express as px
import plotly.graph_objs as go
import sys
import random
Year = 2000
Date = pd.Series(pd.date_range(str(Year) + "-01-01", str(Year) + "-12-31", freq="D"))
Day = Date.diff().astype("timedelta64[D]").fillna(1).cumsum()
dftest = pd.DataFrame({"Day": Day})
dftest = dftest.set_index(Date).reset_index()
dftest = dftest.rename(columns={"index": "Date"})
dftest["Qty"] = [random.randint(1, 10000) for k in dftest.index]
TrendDF = dftest
我的代码是:
def TrendMAn(n):
TrendDF["MAn"] = TrendDF["Qty"].rolling(window=n).mean().set_axis(TrendDF.index)
return TrendDF["MAn"]
fig = go.Figure()
for step in range(1, 20):
fig.add_trace(
go.Scatter(
line=dict(width=2),
x=TrendDF["Date"],
y=TrendMAn(step),
mode="lines",
visible=False,
)
)
fig.add_trace(
go.Scatter(
line=dict(width=2),
x=TrendDF["Date"],
y=savgol_filter(TrendMAn(step), 51, 3),
mode="lines",
visible=False,
)
)
fig.data[14].visible = True
steps = []
for i in range(len(fig.data)):
step = dict(
method="update",
args=[
{"visible": [False] * len(fig.data)},
{"title": "Slider switched to step: " + str(i)},
], # layout attribute
)
step["args"][0]["visible"][i] = True # Toggle i'th trace to "visible"
steps.append(step)
sliders = [
dict(
active=10,
currentvalue={"prefix": "Rolling Average n: "},
pad={"t": 50},
steps=steps,
)
]
fig.update_layout(sliders=sliders)
fig.show()
结果给了我 40 个步骤,而不是 20 个,因为“for 循环”创建了 40 个跟踪,这是有意义的。但是,我想要在同一步骤的“for 循环”中调用的两条跟踪。
由于没有提供过滤函数,因此我重用了移动平均函数并更改了参数以创建两个不同的图形。 Fig.data 与第一个图形、第二个图形、第一个图形之后的下一个索引处的图形以及第二个索引处的图形对齐,因此您可以显示或隐藏添加一行控制线以进行显示和隐藏。
import pandas as pd
import numpy as np
import plotly
import plotly.express as px
import plotly.graph_objs as go
import sys
import random
random.seed(20231129)
Year = 2000
Date = pd.Series(pd.date_range(str(Year) + "-01-01", str(Year) + "-12-31", freq="D"))
Day = Date.diff().astype("timedelta64[D]").fillna(1).cumsum()
dftest = pd.DataFrame({"Day": Day})
dftest = dftest.set_index(Date).reset_index()
dftest = dftest.rename(columns={"index": "Date"})
dftest["Qty"] = [random.randint(1, 10000) for k in dftest.index]
TrendDF = dftest
def TrendMAn(n):
TrendDF["MAn"] = TrendDF["Qty"].rolling(window=n).mean().set_axis(TrendDF.index)
return TrendDF["MAn"]
fig = go.Figure()
for step in range(1, 20):
fig.add_trace(
go.Scatter(
line=dict(width=2),
x=TrendDF["Date"],
y=TrendMAn(step),
mode="lines",
visible=False,
)
)
fig.add_trace(
go.Scatter(
line=dict(width=2),
x=TrendDF["Date"],
#y=savgol_filter(TrendMAn(step), 51, 3),
y=TrendMAn(step+30),
mode="lines",
visible=False,
)
)
fig.data[14].visible = True
fig.data[28].visible = True
steps = []
for i in range(1,20):
step = dict(
method="update",
args=[
{"visible": [False] * len(fig.data)},
{"title": "Slider switched to step: " + str(i)},
], # layout attribute
)
step["args"][0]["visible"][i] = True # Toggle i'th trace to "visible"
step["args"][0]["visible"][i+1] = True # Update
steps.append(step)
sliders = [
dict(
active=10,
currentvalue={"prefix": "Rolling Average n: "},
pad={"t": 50},
steps=steps,
)
]
fig.update_layout(sliders=sliders)
fig.show()