情节:如何防止甘特图中条形的粗细变化?

Plotly: How to prevent varying thickness of bars in a Gantt diagram?

我正在尝试使用示例中的 plotly.express 制作 plotly Gantt 图,但是 plotly 以某种方式根据给定的值改变了条形厚度名称(见图,红色 > 绿色 > 蓝色):

代码如下所示:

import pandas as pd
import plotly.express as px

df = pd.read_csv('Whosebug.csv')
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource", text="Task", width=1600, height=800)
fig.update_yaxes(autorange="reversed")
fig.update_xaxes(
    dtick="1000",
    tickformat="%M:%S",
    ticklabelmode="instant")
fig.update_layout(xaxis_range=[df.Start.min(), df.Finish.max()])
fig.show()

Whosebug.csv 为:

Task,Start,Finish,Workstation,Resource
1,1970-01-01 01:00:00.000,1970-01-01 01:00:05.400,1,ABL
2,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,2,ABS
3,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,3,ABU
4,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,4,ACC
5,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,4,ACC
6,1970-01-01 01:00:03.300,1970-01-01 01:00:05.300,4,ACC
7,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,5,ABS
8,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,6,ACT
9,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,7,ACC
10,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,7,ACC
11,1970-01-01 01:00:03.300,1970-01-01 01:00:05.300,7,ACC
12,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,8,ABS
13,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,9,ABU
14,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,10,ACC
15,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,11,ABS
16,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,12,ABU
17,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,13,ACC
18,1970-01-01 01:00:01.300,1970-01-01 01:00:03.300,13,ACC
19,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,14,ABS
20,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,15,ABP
21,1970-01-01 01:00:00.000,1970-01-01 01:00:01.500,16,ABZ
22,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,17,ACC
23,1970-01-01 01:00:01.300,1970-01-01 01:00:03.300,17,ACC
24,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,18,ABS
25,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,19,AAW
26,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,20,ACC
27,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,20,ACC
28,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,21,ABS
29,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,22,ABU
30,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,23,ACC

我希望所有的条都具有相同的粗细,令人惊讶的是,当我将 Resource 的名称更改为某个随机的 3 字符值时,这会起作用:

我认为这与以AB*AC*开头的资源有关。不幸的是,资源的名称取决于真实世界的名称,所以我不能随意更改它们。当资源名称类似于 FooBar-Axx-FOOxx = [CC, BS, CT...] 时,也会发生变化的条形粗细。有谁知道为什么会发生这种情况或如何防止这种情况?

P.S.:

fig.update_xaxes(
    dtick="1000",
    tickformat="%M:%S")

有必要在甘特图中显示秒而不是天...是否有更好的方法来实现此目的?


更新conda 我用来创建问题的环境 yaml 文件:

name: stack
channels:
  - conda-forge
  - pytorch
  - plotly
dependencies:
    - python>=3.5,<3.8
    - pandas
    - pip
    - pip:
      - plotly

稍作修改的代码仍然会产生如上所示的相同问题:

import pandas as pd
import plotly.express as px
from io import StringIO


csv = """Task,Start,Finish,Workstation,Resource
1,1970-01-01 01:00:00.000,1970-01-01 01:00:05.400,1,ABL
2,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,2,ABS
3,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,3,ABU
4,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,4,ACC
5,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,4,ACC
6,1970-01-01 01:00:03.300,1970-01-01 01:00:05.300,4,ACC
7,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,5,ABS
8,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,6,ACT
9,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,7,ACC
10,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,7,ACC
11,1970-01-01 01:00:03.300,1970-01-01 01:00:05.300,7,ACC
12,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,8,ABS
13,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,9,ABU
14,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,10,ACC
15,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,11,ABS
16,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,12,ABU
17,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,13,ACC
18,1970-01-01 01:00:01.300,1970-01-01 01:00:03.300,13,ACC
19,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,14,ABS
20,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,15,ABP
21,1970-01-01 01:00:00.000,1970-01-01 01:00:01.500,16,ABZ
22,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,17,ACC
23,1970-01-01 01:00:01.300,1970-01-01 01:00:03.300,17,ACC
24,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,18,ABS
25,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,19,AAW
26,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,20,ACC
27,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,20,ACC
28,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,21,ABS
29,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,22,ABU
30,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,23,ACC"""

df = pd.read_csv(StringIO(csv))
# df = pd.read_csv("Whosebug.csv")
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource", text="Task", width=1600, height=800)
fig.update_yaxes(autorange="reversed")
fig.update_xaxes(
    dtick="1000",
    tickformat="%M:%S",
    ticklabelmode="instant")
fig.update_layout(xaxis_range=[df.Start.min(), df.Finish.max()])
fig.show()

conda list的输出:

pip                       20.2.4                     py_0    conda-forge
plotly                    4.12.0                   pypi_0    pypi
python                    3.7.8           h6f2ec95_1_cpython    conda-forge

(这是一个正在进行中的答案,可能会发生变化)


可能的解决方案:

但只有一个 可能的 解决方案,因为我仍然无法 100% 重现您的代码片段和相应的情节。但我们将在细节中更仔细地研究它。你需要最新的 Plotly 版本和 Kaleido。但这些都是非常直接的安装,并且是 plotly 向前迈出的一大步。至少在我看来……

代码 0:

df = pd.read_csv(StringIO(csv))
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource", text="Task", width=1600, height=800)
f2 = fig.full_figure_for_development(warn=False)
f2.layout.barmode = 'group'
f2.show()

地块 0:


详情:


我们必须一步一步来。首先,当我 运行 你提供的代码时,我得到这个:

地块 1:

代码 1:

import pandas as pd
import plotly.express as px
from io import StringIO


csv = """Task,Start,Finish,Workstation,Resource
1,1970-01-01 01:00:00.000,1970-01-01 01:00:05.400,1,ABL
2,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,2,ABS
3,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,3,ABU
4,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,4,ACC
5,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,4,ACC
6,1970-01-01 01:00:03.300,1970-01-01 01:00:05.300,4,ACC
7,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,5,ABS
8,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,6,ACT
9,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,7,ACC
10,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,7,ACC
11,1970-01-01 01:00:03.300,1970-01-01 01:00:05.300,7,ACC
12,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,8,ABS
13,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,9,ABU
14,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,10,ACC
15,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,11,ABS
16,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,12,ABU
17,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,13,ACC
18,1970-01-01 01:00:01.300,1970-01-01 01:00:03.300,13,ACC
19,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,14,ABS
20,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,15,ABP
21,1970-01-01 01:00:00.000,1970-01-01 01:00:01.500,16,ABZ
22,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,17,ACC
23,1970-01-01 01:00:01.300,1970-01-01 01:00:03.300,17,ACC
24,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,18,ABS
25,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,19,AAW
26,1970-01-01 01:00:00.000,1970-01-01 01:00:02.000,20,ACC
27,1970-01-01 01:00:02.000,1970-01-01 01:00:03.300,20,ACC
28,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,21,ABS
29,1970-01-01 01:00:00.000,1970-01-01 01:00:01.000,22,ABU
30,1970-01-01 01:00:00.000,1970-01-01 01:00:01.300,23,ACC"""

df = pd.read_csv(StringIO(csv))
# df = pd.read_csv("Whosebug.csv")
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource", text="Task", width=1600, height=800)
fig.update_yaxes(autorange="reversed")
fig.update_xaxes(
    dtick="1000",
    tickformat="%M:%S",
    ticklabelmode="instant")
fig.update_layout(xaxis_range=[df.Start.min(), df.Finish.max()])
fig.show()

为了接近您提供的屏幕截图,我必须注释掉几行,如下所示。但是还是和你的不一样

情节 2:

代码 2(相同数据集):

df = pd.read_csv(StringIO(csv))
# df = pd.read_csv("Whosebug.csv")
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource", text="Task", width=1600, height=800)
# fig.update_yaxes(autorange="reversed")
# fig.update_xaxes(
#     dtick="1000",
#     tickformat="%M:%S",
#     ticklabelmode="instant")
# fig.update_layout(xaxis_range=[df.Start.min(), df.Finish.max()])
fig.show()

我觉得有点奇怪。可能的解决方案甚至更奇怪。如果您查看 post ,您将了解如何使用 f2 = fig.full_figure_for_development 显示大部分图形属性。您对 f2 所做的任何更改也应该可以对 fig 进行。但在这种情况下不是。为了获得类似于您想要的输出的结果,我必须执行以下操作:

代码 3:

df = pd.read_csv(StringIO(csv))
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource", text="Task", width=1600, height=800)
f2 = fig.full_figure_for_development(warn=False)
f2.layout.barmode = 'group'
f2.show()

情节 3:

也许我们正在取得进展?但现在您可能会想“为什么不 fig.layout.barmode = 'group'?”。那么,这是结果:

情节 4:

代码 4:

df = pd.read_csv(StringIO(csv))
fig = px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource", text="Task", width=1600, height=800)
f2 = fig.full_figure_for_development(warn=False)
# f2.layout.barmode = 'group'
# f2.show()
fig.layout.barmode = 'group'
fig.show()

我觉得整件事有点奇怪。但是请尝试一下,让我知道这一切对您有何影响!