Python Plotly:根据多个时区绘制活跃用户

Python Plotly: Plotting Active Users against multiple timezone

我有这样一个数据集:

>>> data.iloc[5:29]
                    JST                  EST                  UTC  ACTIVE_USER 
5   2021-07-17 00:00:00  2021-07-16 11:00:00  2021-07-16 15:00:00         9339 
6   2021-07-17 01:00:00  2021-07-16 12:00:00  2021-07-16 16:00:00         9499 
7   2021-07-17 02:00:00  2021-07-16 13:00:00  2021-07-16 17:00:00        13652 
8   2021-07-17 03:00:00  2021-07-16 14:00:00  2021-07-16 18:00:00        11897 
9   2021-07-17 04:00:00  2021-07-16 15:00:00  2021-07-16 19:00:00        11961 
10  2021-07-17 05:00:00  2021-07-16 16:00:00  2021-07-16 20:00:00        12192 
11  2021-07-17 06:00:00  2021-07-16 17:00:00  2021-07-16 21:00:00        12339 
12  2021-07-17 07:00:00  2021-07-16 18:00:00  2021-07-16 22:00:00        12174 
13  2021-07-17 08:00:00  2021-07-16 19:00:00  2021-07-16 23:00:00        11627 
14  2021-07-17 09:00:00  2021-07-16 20:00:00  2021-07-17 00:00:00        11607 
15  2021-07-17 10:00:00  2021-07-16 21:00:00  2021-07-17 01:00:00        11120 
16  2021-07-17 11:00:00  2021-07-16 22:00:00  2021-07-17 02:00:00        11600 
17  2021-07-17 12:00:00  2021-07-16 23:00:00  2021-07-17 03:00:00         9739 
18  2021-07-17 13:00:00  2021-07-17 00:00:00  2021-07-17 04:00:00        10269 
19  2021-07-17 14:00:00  2021-07-17 01:00:00  2021-07-17 05:00:00        10779 
20  2021-07-17 15:00:00  2021-07-17 02:00:00  2021-07-17 06:00:00        11339 
21  2021-07-17 16:00:00  2021-07-17 03:00:00  2021-07-17 07:00:00        10920 
22  2021-07-17 17:00:00  2021-07-17 04:00:00  2021-07-17 08:00:00        11631 
23  2021-07-17 18:00:00  2021-07-17 05:00:00  2021-07-17 09:00:00        11316 
24  2021-07-17 19:00:00  2021-07-17 06:00:00  2021-07-17 10:00:00        11464 
25  2021-07-17 20:00:00  2021-07-17 07:00:00  2021-07-17 11:00:00        11825 
26  2021-07-17 21:00:00  2021-07-17 08:00:00  2021-07-17 12:00:00        12319 
27  2021-07-17 22:00:00  2021-07-17 09:00:00  2021-07-17 13:00:00        11474 
28  2021-07-17 23:00:00  2021-07-17 10:00:00  2021-07-17 14:00:00        13952 

我的目标是可视化和分析高峰时段/用户主要基于哪些区域。

通过这个简单的代码,我可以得到一个漂亮的条形图:

import plotly.express as px
import pandas as pd

data = pd.read_csv("proc.csv")

fig = px.bar(data.iloc[5:29], x='JST', y='ACTIVE_USER')

fig.write_html('tmp.html', auto_open=False)

但它只适用于单个时区。我期望的是与此类似的内容:

我检查了 multiple axis function 但它看起来不像我想要的东西。

有没有办法用 Plotly 实现这个?如果有简单的方法,也欢迎与其他图书馆的建议。

一种方法是提出一个结合条形图和 table 的子图。第一个图表用作 JST 的条形图,第二个 table 包含仅针对 EST 和 UTC 时间提取数据的单元格。我们采用子图是因为可以共享 x 轴。但是,它是否满足所有要求尚不清楚,因为它只表示时间。需要注意的是 table 中无法进行文本注释,因此我使用第一个图形标准来确定文本位置。

import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig = make_subplots(
    rows=2, cols=1,
    shared_xaxes=True,
    vertical_spacing=0.08,
    specs=[[{"type": "bar"}],
           [{"type": "table"}]
          ]
)

fig.add_trace(
    go.Bar(
        x=df['JST'],
        y=df["ACTIVE_USER"],
        name='JST'
    ),
    row=1, col=1
)

fig.add_trace(
    go.Table(
        header=dict(
            values=np.arange(0,24,1),
            fill_color='royalblue',
            font=dict(color='white', size=10),
            align="center"
        ),
        cells=dict(
            values=[[x[0][11:13], x[1][11:13]] for x in df[['EST','UTC']].values],
            align="left")
    ),
    row=2, col=1
)

fig.update_layout(
    height=800,
)
fig.add_annotation(x=-0.03, y=-0.35,
                   xref='x domain',
                   yref='y domain',
                   text='EST',
                   showarrow=False,
                   row=1, col=1)

fig.add_annotation(x=-0.03, y=-0.42,
                   xref='x domain',
                   yref='y domain',
                   text='UST',
                   showarrow=False,
                   row=1, col=1)
fig.show()
# fig.write_html('tmp.html', auto_open=False)

px.bar(df, x="JST", y="ACTIVE_USER").add_traces(
    px.bar(df, x="EST", y="ACTIVE_USER").update_traces(xaxis="x2").data
).update_layout(
    xaxis2={
        "title": {"text": "EST", "standoff": 0},
        "position": 0,
    },
    xaxis={"position": 0.2, "title": {"standoff": 0}},
    yaxis={"domain": [0.2, 1]},
    margin={"b": 0},
)