我有一个数据框
df
,其中包含随时间变化的值(过程数据)。我有一个数据框ef
,其中包含具有开始时间和结束时间的事件(警报)。我想以一种美观的方式将它们组合在一个图中。
"""
df==
+---------------------+------------+------------+------------+
| | processA | processB | processC |
|---------------------+------------+------------+------------|
| 2020-01-01 00:00:00 | 101.764 | 20.0079 | 0.978738 |
| 2020-01-01 00:01:00 | 102.241 | 93.3779 | -0.977278 |
| 2020-01-01 00:02:00 | 100.95 | -7.56786 | -0.103219 |
| 2020-01-01 00:03:00 | 100.411 | 7.20218 | 1.45427 |
| 2020-01-01 00:04:00 | 100.761 | 6.08375 | 0.443863 |
+---------------------+------------+------------+------------+
ef==
+----+-----------------------------------------+---------------------+---------------------+----------+
| | alm | Start | Finish | almid |
|----+-----------------------------------------+---------------------+---------------------+----------|
| 0 | alarm A something something has alarmed | 2020-01-01 00:00:30 | 2020-01-01 00:01:30 | alm_id A |
| 1 | alarm B something else happened | 2020-01-01 00:01:30 | 2020-01-01 00:02:30 | alm_id B |
| 2 | alarm A something something has alarmed | 2020-01-01 00:02:00 | 2020-01-01 00:09:30 | alm_id A |
+----+-----------------------------------------+---------------------+---------------------+----------+
"""
我从plotly的文档中收集到的内容,
.create_gantt()
已被弃用。推荐的方法是.timeline()
。我还没有弄清楚如何在 .timeline()
图中自定义任何内容,到目前为止我所拥有的是:
直接关注的问题是:如何自定义条形的位置和宽度。 y 轴上的警报(红色)刻度占用了大量空间,如何更优雅地传达信息。
一个更大的问题是我是否采取了错误的方法?有没有更好的方法(新的图表类型,不同图表的组合)来做到这一点?
PS. 起点:
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import numpy as np
import plotly.io as pio
pio.renderers.default = "browser"
np.random.seed(0)
rowcounts = 10
df = pd.DataFrame(
index = pd.date_range(start=pd.Timestamp('2020-01-01'), freq = 'min', periods=rowcounts, ),
data = np.random.randn(rowcounts, 3), columns=['process'+ x for x in list('ABC')],
)
df.processA += 100
df.processB *= 50
idx = pd.date_range(start=pd.Timestamp('2020-01-01'), freq = '30S', periods=rowcounts*2, )
ef = pd.DataFrame([
dict(alm="alarm A something something has alarmed", Start=idx[1], Finish=idx[3], almid="alm_id A"),
dict(alm="alarm B something else happened", Start=idx[3], Finish=idx[5], almid="alm_id B"),
dict(alm="alarm A something something has alarmed", Start=idx[4], Finish=idx[-1], almid="alm_id A")
])
"""
df==
+---------------------+------------+------------+------------+
| | processA | processB | processC |
|---------------------+------------+------------+------------|
| 2020-01-01 00:00:00 | 101.764 | 20.0079 | 0.978738 |
| 2020-01-01 00:01:00 | 102.241 | 93.3779 | -0.977278 |
| 2020-01-01 00:02:00 | 100.95 | -7.56786 | -0.103219 |
| 2020-01-01 00:03:00 | 100.411 | 7.20218 | 1.45427 |
| 2020-01-01 00:04:00 | 100.761 | 6.08375 | 0.443863 |
+---------------------+------------+------------+------------+
ef==
+----+-----------------------------------------+---------------------+---------------------+----------+
| | alm | Start | Finish | almid |
|----+-----------------------------------------+---------------------+---------------------+----------|
| 0 | alarm A something something has alarmed | 2020-01-01 00:00:30 | 2020-01-01 00:01:30 | alm_id A |
| 1 | alarm B something else happened | 2020-01-01 00:01:30 | 2020-01-01 00:02:30 | alm_id B |
| 2 | alarm A something something has alarmed | 2020-01-01 00:02:00 | 2020-01-01 00:09:30 | alm_id A |
+----+-----------------------------------------+---------------------+---------------------+----------+
"""
fig = px.timeline(
ef, x_start="Start", x_end="Finish", y="alm", color="almid",
color_discrete_map={
"alm_id A": 'rgba(222, 111, 222, .2)',
"alm_id B": 'rgba(111, 222, 222, .2)',
}
)
myfont=dict(
color="red",
family="monospace",
size=14,
)
for c in df.columns:
fig = fig.add_trace(
go.Scatter(
x=df.index,
y=df[c],
name = c,
yaxis = 'y2',
hovertemplate = '%{y} <extra></extra>',
))
fig = fig.update_layout(
xaxis=dict(
type="date",
domain=[0.15,1],
range = [idx[2], idx[10]],
rangeslider=dict(
autorange=True,
visible=True,
),
),
yaxis=dict(
title="alarms",
titlefont=myfont,
tickfont=myfont,
),
yaxis2=dict(
title="processes",
anchor="free",
overlaying="y",
side="left",
position=0.05
),
)
fig = fig.update_yaxes(showline=True, linewidth=2, linecolor='black')
fig.show()
一种可能的选择是这样做:
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import numpy as np
import plotly.io as pio
np.random.seed(0)
rowcounts = 10
df = pd.DataFrame(
index = pd.date_range(start=pd.Timestamp('2020-01-01'), freq = 'min', periods=rowcounts, ),
data = np.random.randn(rowcounts, 3), columns=['process'+ x for x in list('ABC')],
)
df.processA += 100
df.processB *= 50
idx = pd.date_range(start=pd.Timestamp('2020-01-01'), freq = '30S', periods=rowcounts*2, )
ef = pd.DataFrame([
dict(alm="alarm A something something has alarmed", Start=idx[1], Finish=idx[3], almid="alm_id A"),
dict(alm="alarm B something else happened", Start=idx[3], Finish=idx[5], almid="alm_id B"),
dict(alm="alarm A something something has alarmed", Start=idx[4], Finish=idx[-1], almid="alm_id A")
])
这是你的数据
processA processB processC
2020-01-01 00:00:00 101.764052 20.007860 0.978738
2020-01-01 00:01:00 102.240893 93.377900 -0.977278
2020-01-01 00:02:00 100.950088 -7.567860 -0.103219
2020-01-01 00:03:00 100.410599 7.202179 1.454274
2020-01-01 00:04:00 100.761038 6.083751 0.443863
2020-01-01 00:05:00 100.333674 74.703954 -0.205158
2020-01-01 00:06:00 100.313068 -42.704787 -2.552990
2020-01-01 00:07:00 100.653619 43.221810 -0.742165
2020-01-01 00:08:00 102.269755 -72.718284 0.045759
2020-01-01 00:09:00 99.812816 76.638961 1.469359
并绘制它
import plotly.graph_objects as go
import pandas as pd
import numpy as np
fig = go.Figure()
for process in df.columns:
fig.add_trace(go.Scatter(x=df.index, y=df[process], mode='lines', name=process))
for _, alarm in ef.iterrows():
fig.add_shape(type="rect",
x0=alarm['Start'], y0=0, x1=alarm['Finish'], y1=1,
xref='x', yref='paper',
fillcolor="Red", opacity=0.2, line_width=0, layer="below")
fig.update_layout(
yaxis_title='Process Values',
xaxis=dict(title='Time', domain=[0, 0.95]),
legend_title='Process',
hovermode="x unified",
margin=dict(l=20, r=20, t=20, b=20),
height=400, width=800,
)
fig.show()
这给出了
和