Plotly Graph Objects中强制显示所有月份X轴刻度的方法问询
解决Plotly X轴刻度按需显示问题
问题描述
使用plotly.graph_objects生成内嵌数据的HTML图表时,整体体验良好,但存在X轴刻度显示问题:部分场景下刻度无法全部显示,仅在放大视图时才会展示全部刻度(此为放大后的期望行为)。需要实现:
- 展示月份维度数据时,强制显示所有X轴刻度
- 展示全年数据时,不显示所有日刻度(避免过于密集)
当前代码如下:
import pandas as pd import plotly.graph_objects as go list_data_mb = [ ('2023-01-01',10 ,'dat') , ('2023-01-15',15 ,'dat'),('2023-01-01',10 ,'ind') , ('2023-01-15',15 ,'ind'), ('2023-02-01',20 ,'dat') , ('2023-02-15',25 ,'dat'),('2023-02-01',20 ,'ind') , ('2023-02-15',25 ,'ind'), ('2023-03-01',30 ,'dat') , ('2023-03-15',35 ,'dat'),('2023-03-01',30 ,'ind') , ('2023-03-15',35 ,'ind'), ('2023-04-01',40 ,'dat') , ('2023-04-15',45 ,'dat'),('2023-04-01',40 ,'ind') , ('2023-04-15',45 ,'ind'), ('2023-05-01',50 ,'dat') , ('2023-05-15',55 ,'dat'),('2023-05-01',50 ,'ind') , ('2023-05-15',55 ,'ind'), ('2023-06-01',60 ,'dat') , ('2023-06-15',65 ,'dat'),('2023-06-01',60 ,'ind') , ('2023-06-15',65 ,'ind'), ('2023-07-01',70 ,'dat') , ('2023-07-15',75 ,'dat'),('2023-07-01',70 ,'ind') , ('2023-07-15',75 ,'ind'), ('2023-08-01',80 ,'dat') , ('2023-08-15',85 ,'dat'),('2023-08-01',80 ,'ind') , ('2023-08-15',85 ,'ind'), ('2023-09-01',90 ,'dat') , ('2023-09-15',95 ,'dat'),('2023-09-01',90 ,'ind') , ('2023-09-15',95 ,'ind'), ('2023-10-01',100,'dat') , ('2023-10-15',102,'dat'),('2023-10-01',100,'ind') , ('2023-10-15',102,'ind'), ('2023-11-01',104,'dat') , ('2023-11-15',106,'dat'),('2023-11-01',104,'ind') , ('2023-11-15',106,'ind'), ('2023-12-01',108,'dat') , ('2023-12-15',110,'dat'),('2023-12-01',108,'ind') , ('2023-12-15',108,'ind'), ('2024-01-01',112,'dat') , ('2024-01-15',114,'dat'),('2024-01-01',112,'ind') , ('2024-01-15',114,'ind'), ] df = pd.DataFrame(list_data_mb,columns=['date','size','tbs']) df['date'] = pd.to_datetime(df['date'], format="%Y-%m-%d") data = [go.Bar(name=tbs, x=dfg['date'], y=dfg['size']) for tbs,dfg in df.groupby(by='tbs')] fig = go.Figure(data) fig.update_layout( barmode = 'stack', title = 'Tablespaces size over time', xaxis_title = 'Date', ) fig.update_xaxes( rangeslider_visible=True, tickmode='array', #linear: too many values. And for "1d", it will not display hours rangeselector=dict( buttons=list([ dict(count=1, label="1d" , step="day", stepmode="backward"), dict(count=1, label="1m" , step="month", stepmode="backward"), dict(count=6, label="6m" , step="month", stepmode="backward"), dict(count=1, label="1y" , step="year", stepmode="backward"), dict(count=1, label="YTD", step="year", stepmode="todate" ), dict( step="all" ) ]) ) ) fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='white') fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='white') fig.write_html("./aux_0.html")
解决方案
要实现按需显示刻度的需求,关键是自定义X轴的刻度值数组,并让Plotly根据当前视图范围自动筛选显示的刻度,具体修改如下:
- 提取所有唯一日期作为刻度值:从数据中获取不重复的日期并排序,作为X轴的候选刻度
- 配置刻度文本与显示参数:设置刻度文本格式,旋转标签避免重叠,同时限制最大显示刻度数,确保大范围视图不会过于密集
修改后的核心代码部分:
# 提取并排序所有唯一日期 unique_dates = sorted(df['date'].unique()) # 更新X轴配置 fig.update_xaxes( rangeslider_visible=True, tickmode='array', tickvals=unique_dates, # 设置候选刻度值 ticktext=[d.strftime('%Y-%m-%d') for d in unique_dates], # 格式化刻度文本 tickangle=45, # 旋转刻度标签,避免重叠 nticks=12, # 控制最大显示刻度数,全年视图时自动合并 rangeselector=dict( buttons=list([ dict(count=1, label="1d" , step="day", stepmode="backward"), dict(count=1, label="1m" , step="month", stepmode="backward"), dict(count=6, label="6m" , step="month", stepmode="backward"), dict(count=1, label="1y" , step="year", stepmode="backward"), dict(count=1, label="YTD", step="year", stepmode="todate" ), dict( step="all" ) ]) ) )
完整修改后代码
import pandas as pd import plotly.graph_objects as go list_data_mb = [ ('2023-01-01',10 ,'dat') , ('2023-01-15',15 ,'dat'),('2023-01-01',10 ,'ind') , ('2023-01-15',15 ,'ind'), ('2023-02-01',20 ,'dat') , ('2023-02-15',25 ,'dat'),('2023-02-01',20 ,'ind') , ('2023-02-15',25 ,'ind'), ('2023-03-01',30 ,'dat') , ('2023-03-15',35 ,'dat'),('2023-03-01',30 ,'ind') , ('2023-03-15',35 ,'ind'), ('2023-04-01',40 ,'dat') , ('2023-04-15',45 ,'dat'),('2023-04-01',40 ,'ind') , ('2023-04-15',45 ,'ind'), ('2023-05-01',50 ,'dat') , ('2023-05-15',55 ,'dat'),('2023-05-01',50 ,'ind') , ('2023-05-15',55 ,'ind'), ('2023-06-01',60 ,'dat') , ('2023-06-15',65 ,'dat'),('2023-06-01',60 ,'ind') , ('2023-06-15',65 ,'ind'), ('2023-07-01',70 ,'dat') , ('2023-07-15',75 ,'dat'),('2023-07-01',70 ,'ind') , ('2023-07-15',75 ,'ind'), ('2023-08-01',80 ,'dat') , ('2023-08-15',85 ,'dat'),('2023-08-01',80 ,'ind') , ('2023-08-15',85 ,'ind'), ('2023-09-01',90 ,'dat') , ('2023-09-15',95 ,'dat'),('2023-09-01',90 ,'ind') , ('2023-09-15',95 ,'ind'), ('2023-10-01',100,'dat') , ('2023-10-15',102,'dat'),('2023-10-01',100,'ind') , ('2023-10-15',102,'ind'), ('2023-11-01',104,'dat') , ('2023-11-15',106,'dat'),('2023-11-01',104,'ind') , ('2023-11-15',106,'ind'), ('2023-12-01',108,'dat') , ('2023-12-15',110,'dat'),('2023-12-01',108,'ind') , ('2023-12-15',108,'ind'), ('2024-01-01',112,'dat') , ('2024-01-15',114,'dat'),('2024-01-01',112,'ind') , ('2024-01-15',114,'ind'), ]) df = pd.DataFrame(list_data_mb,columns=['date','size','tbs']) df['date'] = pd.to_datetime(df['date'], format="%Y-%m-%d") data = [go.Bar(name=tbs, x=dfg['date'], y=dfg['size']) for tbs,dfg in df.groupby(by='tbs')] fig = go.Figure(data) fig.update_layout( barmode = 'stack', title = 'Tablespaces size over time', xaxis_title = 'Date', ) # 提取并排序所有唯一日期 unique_dates = sorted(df['date'].unique()) fig.update_xaxes( rangeslider_visible=True, tickmode='array', tickvals=unique_dates, ticktext=[d.strftime('%Y-%m-%d') for d in unique_dates], tickangle=45, nticks=12, rangeselector=dict( buttons=list([ dict(count=1, label="1d" , step="day", stepmode="backward"), dict(count=1, label="1m" , step="month", stepmode="backward"), dict(count=6, label="6m" , step="month", stepmode="backward"), dict(count=1, label="1y" , step="year", stepmode="backward"), dict(count=1, label="YTD", step="year", stepmode="todate" ), dict( step="all" ) ]) ) ) fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='white') fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='white') fig.write_html("./aux_0.html")
效果说明
- 当选择1m(1个月)视图时,X轴会自动显示该月的所有刻度(1号和15号)
- 当选择全年或6m视图时,Plotly会根据
nticks参数自动筛选显示的刻度,避免日刻度过于密集,仅展示关键日期或合并为月份级别的刻度 - 旋转刻度标签(
tickangle=45)可以避免标签重叠,提升可读性
内容的提问来源于stack exchange,提问作者glezo
相关产品推荐
相关产品推荐

