如何在Plotly矩形热力图中添加细灰线区分日期与Physician
问题
我目前正在使用Plotly制作一张展示各医生(Physician)排班情况的图表,该图表目前略显混乱,我希望对其进行修改:是否可以在各个矩形之间添加细灰线,以便从视觉上区分不同日期与医生?
以下是实现该图表的代码:
def visualize_schedule(days, undercoverage): dic = {(1, 1, 1): 1.0, (1, 1, 2): 0.0, (1, 1, 3): 0.0, (1, 2, 1): 0.0, (1, 2, 2): 1.0, (1, 2, 3): 0.0, (1, 3, 1): 0.0, (1, 3, 2): 0.0, (1, 3, 3): 0.0, (1, 4, 1): 0.0, (1, 4, 2): 1.0, (1, 4, 3): 0.0, (1, 5, 1): 1.0, (1, 5, 2): 0.0, (1, 5, 3): 0.0, (1, 6, 1): 0.0, (1, 6, 2): 1.0, (1, 6, 3): 0.0, (1, 7, 1): 0.0, (1, 7, 2): 1.0, (1, 7, 3): 0.0, (2, 1, 1): 1.0, (2, 1, 2): 0.0, (2, 1, 3): 0.0, (2, 2, 1): 1.0, (2, 2, 2): 0.0, (2, 2, 3): 0.0, (2, 3, 1): 1.0, (2, 3, 2): 0.0, (2, 3, 3): 0.0, (2, 4, 1): 0.0, (2, 4, 2): 0.0, (2, 4, 3): 0.0, (2, 5, 1): 1.0, (2, 5, 2): 0.0, (2, 5, 3): 0.0, (2, 6, 1): 0.0, (2, 6, 2): 0.0, (2, 6, 3): 1.0, (2, 7, 1): 0.0, (2, 7, 2): 1.0, (2, 7, 3): 0.0, (3, 1, 1): 1.0, (3, 1, 2): 0.0, (3, 1, 3): 0.0, (3, 2, 1): 0.0, (3, 2, 2): 1.0, (3, 2, 3): 0.0, (3, 3, 1): 0.0, (3, 3, 2): 0.0, (3, 3, 3): 0.0, (3, 4, 1): 1.0, (3, 4, 2): 0.0, (3, 4, 3): 0.0, (3, 5, 1): 1.0, (3, 5, 2): 0.0, (3, 5, 3): 0.0, (3, 6, 1): 1.0, (3, 6, 2): 0.0, (3, 6, 3): 0.0, (3, 7, 1): 0.0, (3, 7, 2): 1.0, (3, 7, 3): 0.0} s = pd.Series(dic) data = (s.loc[lambda s: s == 1] .reset_index(-1)['level_2'].unstack(fill_value=0) .reindex(index=s.index.get_level_values(0).unique(), columns=s.index.get_level_values(1).unique(), fill_value=0 ) ) data.index = data.index.astype(int) data.columns = data.columns.astype(str) title_str = f'Physician Schedules | Total Undercoverage: {undercoverage}' fig = px.imshow(data[[str(i) for i in range(1, days + 1)]], color_continuous_scale=["purple", "orange", "yellow", 'pink']) fig.update(data=[{'hovertemplate': "Day: %{x}<br>" "Physician: %{y}<br>"}]) colorbar = dict(thickness=35, tickvals=[0, 1, 2, 3], ticktext=['Off', 'Evening', 'Noon', 'Morning']) fig.update(layout_coloraxis_showscale=True, layout_coloraxis_colorbar=colorbar) x_ticks = np.arange(1, days + 1) day_labels = ['Day ' + str(i) for i in x_ticks] fig.update_xaxes(tickvals=x_ticks, ticktext=day_labels) y_ticks = np.arange(1, data.shape[0] + 1) physician_labels = ['Physician ' + str(i) for i in y_ticks] fig.update_yaxes(tickvals=y_ticks, ticktext=physician_labels) fig.update_layout( title={ 'text': title_str, 'y': 0.98, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top', 'font': {'size': 24} } ) fig.update_layout( xaxis=dict( showgrid=True, gridwidth=1.5, gridcolor='LightGray' ), yaxis=dict( showgrid=True, gridwidth=1.5, gridcolor='LightGray' ) ) fig.show() return fig
解决方案
要在每个排班矩形之间添加精准的细灰线,核心是让网格线对齐到矩形的边界而非默认的中心位置,同时优化网格线的视觉效果。以下是修改后的实现:
修改后的完整代码
def visualize_schedule(days, undercoverage): dic = {(1, 1, 1): 1.0, (1, 1, 2): 0.0, (1, 1, 3): 0.0, (1, 2, 1): 0.0, (1, 2, 2): 1.0, (1, 2, 3): 0.0, (1, 3, 1): 0.0, (1, 3, 2): 0.0, (1, 3, 3): 0.0, (1, 4, 1): 0.0, (1, 4, 2): 1.0, (1, 4, 3): 0.0, (1, 5, 1): 1.0, (1, 5, 2): 0.0, (1, 5, 3): 0.0, (1, 6, 1): 0.0, (1, 6, 2): 1.0, (1, 6, 3): 0.0, (1, 7, 1): 0.0, (1, 7, 2): 1.0, (1, 7, 3): 0.0, (2, 1, 1): 1.0, (2, 1, 2): 0.0, (2, 1, 3): 0.0, (2, 2, 1): 1.0, (2, 2, 2): 0.0, (2, 2, 3): 0.0, (2, 3, 1): 1.0, (2, 3, 2): 0.0, (2, 3, 3): 0.0, (2, 4, 1): 0.0, (2, 4, 2): 0.0, (2, 4, 3): 0.0, (2, 5, 1): 1.0, (2, 5, 2): 0.0, (2, 5, 3): 0.0, (2, 6, 1): 0.0, (2, 6, 2): 0.0, (2, 6, 3): 1.0, (2, 7, 1): 0.0, (2, 7, 2): 1.0, (2, 7, 3): 0.0, (3, 1, 1): 1.0, (3, 1, 2): 0.0, (3, 1, 3): 0.0, (3, 2, 1): 0.0, (3, 2, 2): 1.0, (3, 2, 3): 0.0, (3, 3, 1): 0.0, (3, 3, 2): 0.0, (3, 3, 3): 0.0, (3, 4, 1): 1.0, (3, 4, 2): 0.0, (3, 4, 3): 0.0, (3, 5, 1): 1.0, (3, 5, 2): 0.0, (3, 5, 3): 0.0, (3, 6, 1): 1.0, (3, 6, 2): 0.0, (3, 6, 3): 0.0, (3, 7, 1): 0.0, (3, 7, 2): 1.0, (3, 7, 3): 0.0} s = pd.Series(dic) data = (s.loc[lambda s: s == 1] .reset_index(-1)['level_2'].unstack(fill_value=0) .reindex(index=s.index.get_level_values(0).unique(), columns=s.index.get_level_values(1).unique(), fill_value=0 ) ) data.index = data.index.astype(int) data.columns = data.columns.astype(str) title_str = f'医生排班表 | 总缺口数: {undercoverage}' fig = px.imshow(data[[str(i) for i in range(1, days + 1)]], color_continuous_scale=["purple", "orange", "yellow", 'pink']) fig.update(data=[{'hovertemplate': "日期: %{x}<br>" "医生: %{y}<br>"}]) colorbar = dict(thickness=35, tickvals=[0, 1, 2, 3], ticktext=['休息', '晚班', '午班', '早班']) fig.update(layout_coloraxis_showscale=True, layout_coloraxis_colorbar=colorbar) x_ticks = np.arange(1, days + 1) day_labels = ['第' + str(i) + '天' for i in x_ticks] fig.update_xaxes( tickvals=x_ticks, ticktext=day_labels, showgrid=True, gridwidth=1, gridcolor='LightGray', range=[0.5, days + 0.5], dtick=1 ) y_ticks = np.arange(1, data.shape[0] + 1) physician_labels = ['医生' + str(i) for i in y_ticks] fig.update_yaxes( tickvals=y_ticks, ticktext=physician_labels, showgrid=True, gridwidth=1, gridcolor='LightGray', range=[0.5, data.shape[0] + 0.5], dtick=1 ) fig.update_layout( title={ 'text': title_str, 'y': 0.98, 'x': 0.5, 'xanchor': 'center', 'yanchor': 'top', 'font': {'size': 24} } ) fig.show() return fig
关键修改说明
- 轴范围校准:通过设置
range=[0.5, days + 0.5](X轴)和range=[0.5, data.shape[0] + 0.5](Y轴),让坐标轴的起点和终点落在第一个和最后一个矩形的边缘,确保网格线能精准分隔每个排班块。 - 网格线优化:将
gridwidth从1.5调整为1,保持细灰线的视觉简洁性,避免干扰排班信息的展示。 - 中文适配:将标题、悬停提示、刻度标签等内容改为中文,更符合国内使用习惯(若不需要可直接改回英文)。
内容的提问来源于stack exchange,提问作者nflgreaternba
相关产品推荐
相关产品推荐

