You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

关键修改说明

  1. 轴范围校准:通过设置range=[0.5, days + 0.5](X轴)和range=[0.5, data.shape[0] + 0.5](Y轴),让坐标轴的起点和终点落在第一个和最后一个矩形的边缘,确保网格线能精准分隔每个排班块。
  2. 网格线优化:将gridwidth从1.5调整为1,保持细灰线的视觉简洁性,避免干扰排班信息的展示。
  3. 中文适配:将标题、悬停提示、刻度标签等内容改为中文,更符合国内使用习惯(若不需要可直接改回英文)。

内容的提问来源于stack exchange,提问作者nflgreaternba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:17:02