如何绘制彩色甘特图并保持正确的条高

How to plot a colored gantt chart with plotly keeping the correct bar height

我有以下代码可以绘制甘特图:

import datetime
import pandas
import plotly.express as px

task_list = [{
    'Task': 'T-3', 'y': 0, 'Start': datetime.date(2022, 2, 24),
    'Finish': datetime.date(2022, 3, 17), 'Status': 'Scheduled'}, {
    'Task': 'SNP-350', 'y': 1, 'Start': datetime.date(2022, 2, 24),
    'Finish': datetime.date(2022, 2, 25), 'Status': 'Backlog'}, {
    'Task': 'RD-6687', 'y': 2, 'Start': datetime.date(2022, 3, 18),
    'Finish': datetime.date(2022, 4, 8), 'Status': 'Selected'}, {
    'Task': 'RD-6643', 'y': 3, 'Start': datetime.date(2022, 2, 24),
    'Finish': datetime.date(2022, 3, 17), 'Status': 'Scheduled'}, {
    'Task': 'SNP-337', 'y': 4, 'Start': datetime.date(2022, 5, 21),
    'Finish': datetime.date(2022, 5, 23), 'Status': 'Backlog'}, {
    'Task': 'SNP-352', 'y': 5, 'Start': datetime.date(2022, 2, 26),
    'Finish': datetime.date(2022, 2, 28), 'Status': 'Clarification'}, {
    'Task': 'SNP-239', 'y': 6, 'Start': datetime.date(2022, 5, 24),
    'Finish': datetime.date(2022, 5, 25), 'Status': 'Selected'}]

df = pandas.DataFrame(task_list)

fig = px.timeline(df, x_start="Start", x_end="Finish", y="y",
                  # color="Status",
                  )

fig.show()

这给了我预期的甘特图:

但是,如果我现在包含上面代码中注释掉的行,即根据状态在甘特图中为条形图着色,则会弄乱不同条形图的高度:

所以颜色按预期显示,但似乎不同条的高度现在不受相邻条的限制,而仅受具有相同颜色的相邻条的限制。如何将颜色添加到甘特图,同时保持条形图没有颜色时的高度?

  • 使用 color 为每个 Status 创建轨迹,因此高度发生变化
  • 已将 状态 放入 hover_data
  • 构建 colormap 然后更新跟踪以使用 Status 的值来查找颜色
import datetime
import pandas
import plotly.express as px
import numpy as np

# fmt: off
task_list = [{
    'Task': 'T-3', 'y': 0, 'Start': datetime.date(2022, 2, 24),
    'Finish': datetime.date(2022, 3, 17), 'Status': 'Scheduled'}, {
    'Task': 'SNP-350', 'y': 1, 'Start': datetime.date(2022, 2, 24),
    'Finish': datetime.date(2022, 2, 25), 'Status': 'Backlog'}, {
    'Task': 'RD-6687', 'y': 2, 'Start': datetime.date(2022, 3, 18),
    'Finish': datetime.date(2022, 4, 8), 'Status': 'Selected'}, {
    'Task': 'RD-6643', 'y': 3, 'Start': datetime.date(2022, 2, 24),
    'Finish': datetime.date(2022, 3, 17), 'Status': 'Scheduled'}, {
    'Task': 'SNP-337', 'y': 4, 'Start': datetime.date(2022, 5, 21),
    'Finish': datetime.date(2022, 5, 23), 'Status': 'Backlog'}, {
    'Task': 'SNP-352', 'y': 5, 'Start': datetime.date(2022, 2, 26),
    'Finish': datetime.date(2022, 2, 28), 'Status': 'Clarification'}, {
    'Task': 'SNP-239', 'y': 6, 'Start': datetime.date(2022, 5, 24),
    'Finish': datetime.date(2022, 5, 25), 'Status': 'Selected'}]
# fmt: on
df = pandas.DataFrame(task_list)

# put status into figure as well as customdata
fig = px.timeline(
    df,
    x_start="Start",
    x_end="Finish",
    y="y",
    # color="Status",
    hover_data=["Status"],
)

# build a colormap for status 
colormap = {s:c for s,c in zip(df["Status"].unique(), px.colors.qualitative.Plotly)}
# use status in customdata to map color
fig.update_traces(marker_color=[colormap[s[0]] for s in fig.data[0].customdata])