当前位置: 首页 > 知识库问答 >
问题:

绘制甘特图:删除重复的Y轴标签并堆叠并行任务

欧阳洲
2023-03-14

我计划使用python库“Plotly”构建甘特图。具体而言:https://plotly.com/python/gantt/#group-一起完成任务。

然而,每个“作业”可以有多个任务,并且这些任务可以并行运行。从我观察到的情况来看,Plotly并没有将并行运行的任务堆叠在一起,这使得读取图表非常困难。下面是一个示例,“作业A”有两个并行运行的任务,但只有一个可见:

data = [dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
      dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
      dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15'),
      dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30')]

# Without group_tasks=True, There would be two separate "Job A" labels
fig = ff.create_gantt(data, group_tasks=True)
fig.show()

我想要的是“作业A”任务都是可见的,但要垂直堆叠,“作业A”位于其任务占用的垂直空间的中心。类似这样,但没有两个“工作A”标签:

如果有人对我的甘特图项目有任何库建议,我应该考虑,请随时分享!谢谢!

共有2个答案

郗亦
2023-03-14
import plotly.express as px
import pandas as pd

data = [dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
      dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
      dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15'),
      dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30')]

df = pd.DataFrame(data)

df['JobNum'] = ""
df.loc[0,'JobNum'] = 1
for idx in range(1,df.shape[0]):
    if df.loc[idx-1,'Task'] == df.loc[idx,'Task']:
        df.loc[idx,'JobNum'] = df.loc[idx-1,'JobNum'] + 1
    else:
        df.loc[idx,'JobNum'] = 1

df['hoverName'] = df.apply(lambda x: x['Task'] + "|" + str(x['JobNum']), axis=1)

方法1:使用Facet行

fig = px.timeline(df
                  , x_start="Start"
                  , x_end="Finish"
                  , y="Task"
                  , hover_name= "Task"
                  , color_discrete_sequence=px.colors.qualitative.Prism
                  , opacity=.7
                  , template='plotly_white'
                  , color='Task'
                  , facet_row= 'JobNum'
                  , hover_data = ['Start','Finish']
                 )
fig.show()

Appraoch 1输出

近似值2:调整宽度和偏移。当有两个以上的并行任务时,这需要推广。

fig = px.timeline(df
                  , x_start="Start"
                  , x_end="Finish"
                  , y="Task"
                  , hover_name= "hoverName"
                  , color_discrete_sequence=px.colors.qualitative.Prism
                  , opacity=.7
                  , template='plotly_white'
                  , color='JobNum'
                  , hover_data = ['Start','Finish']
                 )

for obj in fig.data:
    Task, JobNum = obj.hovertext[0].split("|")
    if (int(JobNum) == 1):
        obj.width = 0.1
        obj.offset = 0.05
    elif (int(JobNum) == 2):
        obj.width = 0.1
        obj.offset = -0.05

fig.show()

方法2输出

李博达
2023-03-14

一个起点是使用fig.add_shape添加一个相同的任务作为原始任务下方的矩形。

要做到这一点,我们需要每个矩形的y坐标,但方便的是,第一个条位于y=0,第二个条位于y=1,依此类推。因此,按顺序列出的唯一任务的索引也是y坐标(唯一任务是[作业A、作业B、作业C],因此作业C栏将居中于y=3)。每个条的默认宽度为0.8,因此如果y0是条的起始y坐标,则y1应结束于y0-0.4。

请注意,带注释的形状没有任何悬停模板,每个条的颜色与当前编写的颜色相同。

import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

## added additional duplicate Task to demonstrate generalizability
data = [dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
      dict(Task="Job A", Start='2009-01-01', Finish='2009-02-28'),
      dict(Task="Job B", Start='2009-03-05', Finish='2009-04-15'),
      dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30'),
      dict(Task="Job C", Start='2009-02-20', Finish='2009-05-30')]

df = pd.DataFrame(data)

# Without group_tasks=True, There would be two separate "Job A" labels
# fig = ff.create_gantt(data, group_tasks=True)

## plot the non-duplicate rows
fig = px.timeline(df.loc[~df['Task'].duplicated()], x_start="Start", x_end="Finish", y="Task")

## plot the duplicate rows using rectangular shapes
for row in df.loc[df['Task'].duplicated()].itertuples():
      y_val = np.where(df.Task.unique()==row[1])[0][0]
      # print(f"found {row[1]} at index {y_val}")
      fig.add_shape(type="rect",
            xref="x", yref="y",
            x0=row[2], x1=row[3], 
            y0=y_val, y1=y_val-0.4,
            line_width=0,
            fillcolor="salmon",
)
fig.show()

 类似资料:
  • 我正在创建一个JFreeChart堆叠区域图表。 我希望我的y轴标签的宽度是固定的,我不想移动图表随着宽度的增加。见说明问题的图像。 我也面临着JFreeChart论坛上发布的类似问题。根据论坛,它是固定的,但它还没有发布。有没有人知道它的解决办法。我们迫不及待地等待下一个版本,有谁知道我们可以应用的黑客吗? 希望能找到解决办法。

  • 我回顾了这个问题的答案,其中提出了一些后续问题,涉及将解决方案泛化以支持每个类别的可变行数,现在我已经准备好了代码,可以将各种任务拆分为所需的行。 我已经使用了原来的小提琴并对其进行了修改,看到这里可以更好地理解这个概念。 我可以看到我们有一个必须一起工作的数字。我们首先似乎需要为每个将有多行的类别中断,我们需要将“y”属性设置为类别偏移量的十进制部分,并且我们需要在类别系列上应用翻译。 目前尚不

  • 问题内容: 我正在根据创建一个图: 问题是x和y轴中有不想要的标签,这些标签来自层次结构索引。因此,我想尝试删除这些标签,例如: 但这没有效果。如何删除x和y轴上的标签? 问题答案: 没有这个问题,就很难知道标签来自何处(我不知道数据帧的外观如何,这样才能产生标签,因为默认情况下不应有任何标签。)但是,标签可以使用已知方法和群集网格的热图轴进行设置- 因此也设置为空字符串。 所以如果是一个实例,

  • 我不熟悉plotly,我有一些start=int和finish=int(以抽象时间单位)的任务。但x轴默认为日期格式。我想将x轴设置为数字格式(0,1,2…) 这是我的代码: df看起来像: 任何建议!

  • 这些是输入数据("test.data")的几个留置权: 我使用此代码绘制甘特图: 输出如下所示: 我想知道,我怎样才能从绿色矩形的两侧去掉那些白点?或者至少改变他们的颜色?

  • 我将甘特图(ChartPanel)放在JScrollPane中,并创建一个名为[zoom in]的按钮。 按钮[zoom in]的功能是: 当我单击[zoom in]按钮时,图表面板的宽度将加倍。 点击【放大】按钮后,会出现JScrollPane的滚动条。 然后用户可以在放大后滚动观看整个图表。 但是有一个问题,当我加倍图表面板宽度时,任务标签字体也会放大。 在我把图表面板的宽度增加一倍后,有没有