Plotly - x轴上多个(三个)标签
我有一个数据集,里面有周、月和年的列,我想用这些周、月和年作为标签来绘制一个时间变化的图表。请问在Python的plotly库中可以做到这样吗?
我已经能用以下代码得到两个标签(周和月)了:df是我的数据框,里面有周、月、年和数值这几列。
fig = go.Figure()
fig.add_trace(go.Scatter(x=[df['month'], df['week']],
y=list(df['value'])))
return fig
2 个回答
1
你可以在图表中添加一个辅助的X轴,把每周的刻度和标签放在上面。如果你需要一些特别的年份刻度,也可以把它们放在这个辅助X轴上,位置在图表外面:
import plotly.graph_objects as go
from plotly.graph_objs.layout import YAxis, XAxis
import plotly.express as px
df = px.data.stocks()
# grab some data
df = df.head(60)
# apply the layout with a secondary X-axis
layout = go.Layout(
title="Plot with ticks for weeks, months, and years on the X-axis",
# main X-axis with monthly ticks, where each label contains a month and a year
xaxis = XAxis(
ticks="outside",
ticklabelmode="period",
tickcolor="black",
ticklen=10,
dtick="M1",
tickformat="%m\n%Y"
),
# secondary X-axis having weekly ticks with inside labels, and having huge outside "minor" ticks corresponding to years
xaxis2 = XAxis(
overlaying="x",
ticks="inside",
ticklabelposition="inside",
ticklabelmode="period",
tickcolor="black",
ticklen=10,
dtick=7*24*60*60*1000,
tickformat="%V",
griddash="dot",
gridcolor="white",
minor=dict(
ticks="outside",
ticklen=40,
dtick="M12"
)
),
yaxis=dict(
title="Y values"
),
)
# plot data
fig = px.line(df, x="date", y=df.columns,
title="custom tick labels")
# apply the layout with a secondary X-axis
fig.update_layout(layout)
# place an invisible trace on the secondary X axis, to avoid automatic hiding of the axis
fig.add_trace(
go.Scatter(x=df["date"], y=df["GOOG"], name="some data", xaxis="x2", opacity=0, showlegend=False),
)
fig.show()
在这个方法中,你需要在辅助X轴上放置一个透明的轨迹,否则Plotly会自动隐藏这个轴。结果如下:
如果你缩放这个包含图片的HTML页面,可能会发现每周的标签变成了竖着的:
如果你把页面压缩得太厉害,标签甚至可能会重叠在一起:
为了避免这种情况,你可能需要调整一下dtick参数,这个参数在这里表示刻度之间的间隔,单位是毫秒。例如,如果你从辅助X轴的布局定义中去掉dtick=7*24*60*60*1000,
,那么在辅助X轴上只会显示部分每周的标签:
但是如果你把图放大到一定程度,你会再次看到所有的标签:
2
据我所知,x轴上最多可以有两个层级的层次结构。作为一种解决方法,你可以把年份和月份结合起来,这样就能得到接近你想要的效果。我是根据参考中的散点图代码创建的。
import plotly.express as px
import plotly.graph_objects as go
import datetime
import pandas as pd
df = px.data.stocks()[:30]
df['date'] = pd.to_datetime(df['date'])
df['week'] = df['date'].dt.isocalendar().week
df['month'] = df['date'].dt.month
df['year'] = df['date'].dt.year
fig = go.Figure()
fig.add_trace(go.Scatter(x=[[f'{m:02}<br>{y}' for y,m in zip(df['year'].tolist(),df['month'].tolist())], df['week']], y=list(df['GOOG'])))
fig.show()