有没有办法在python中创建甘特图? [英] Is there a way to create gantt charts in python?

查看:101
本文介绍了有没有办法在python中创建甘特图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 create_gantt 在 python 中创建甘特图.但是,当开始日期和结束日期重叠时,我会遇到问题.

例如:

import plotly.plotly as py导入 plotly.figure_factory 作为 ff情节导入df = [dict(Task="Milestone A", Start='2017-01-01', Finish='2017-02-02', Resource='Jack'),dict(Task="Milestone B", Start='2018-01-01', Finish='2018-02-02', Resource='Jack'),dict(Task="Milestone A", Start='2017-01-17', Finish='2017-04-28', Resource='Joe'),dict(Task="Milestone B", Start='2017-03-17', Finish='2017-04-28', Resource='Joe'),dict(Task="Milestone A", Start='2017-01-14', Finish='2017-03-14', Resource='John'),dict(Task="Milestone B", Start='2018-01-14', Finish='2018-03-14', Resource='John')]颜色 = {'Jack': 'rgb(220, 0, 0)','乔': (1, 0.9, 0.16),'约翰':'rgb(0, 255, 100)'}fig = ff.create_gantt(df, 颜色=颜色, index_col='Resource', show_colorbar=True, group_tasks=True)plotly.offline.plot(fig, filename='gantt-group-tasks-together')

当我运行这段代码时,Joe、Jack 和 John 的小节线与里程碑 A 和里程碑 B 重叠,如图所示.

示例 df:

- ----------------------------------- ------------------- -------------------- ---------------------------------0 数据类型处理/自动推理 2019-07-01 00:00:00 2019-07-31 00:00:00 后端1 Sklearn &其他型号 2019-07-01 00:00:00 2019-07-31 00:00:00 型号2 地图/地理绘图 2019-07-01 00:00:00 2019-07-31 00:00:00 后端,图形用户界面3 优化 Dockerfile 2019-07-01 00:00:00 2019-07-31 00:00:00 CI/CD4 第 2 章:比较竞争对手 2019-07-08 00:00:00 2019-10-21 00:00:00 写作- ------------------------------------ ------------------- ------------------- ---------------------------------

我还找到了一种添加文本并使其看起来好像有进度条的方法.它的工作原理是创建另一个系列,其条形的高度等于 original * progress 并将其附加到原始数据帧

# 使用进度找出应该填充多少条#(即另一​​个结束日期)df["进度日期"] = (df["结束日期"] - df["开始日期"]) * df["进度%"]/100 + df["开始日期"]# 连接两个newdf = np.concatenate([df[["Task Name", "Start date", "End date", "Progress %"]].values,df[["任务名称", "开始日期", "进度日期", "进度%"]].values])newdf = pd.DataFrame(newdf, columns=["任务名称", "开始日期", "结束日期", "进度%"])# 重新转换回日期时间newdf["开始日期"] = pd.to_datetime(newdf["开始日期"])newdf["结束日期"] = pd.to_datetime(newdf["结束日期"])# 这是分组发生的指示变量(持续时间与进度)newdf["progress_"] = np.concatenate([np.ones(len(newdf)//2), np.zeros(len(newdf)//2), ])# 上半场颜色,下半场颜色range_ = ['#1f77b4', '#5fa0d4',]# 堆积条形图将是我们的进度甘特图"图表 = alt.Chart(newdf).mark_bar().encode(x=alt.X('开始日期', stack=None),x2='结束日期',y=alt.Y('任务名称', sort=list(df.sort_values(["结束日期","开始日期"])["任务名称"])*2),color=alt.Color('progress_', scale=alt.Scale(range=range_), legend=None))# 创建合适的标签newdf["text%"] = newdf["进度%"].astype(str) + "%"# 现在将它们作为文本添加到图表中text = alt.Chart(newdf).mark_text(align='left', baseline='middle', dx=5, color="white", fontWeight="bold").encode(y=alt.Y('任务名称', sort=list(df.sort_values(["结束日期","开始日期"])["任务名称"])*2),x=alt.X('开始日期'),文字='文字%',)# 绘制图形alt.layer(图表,文本)

结果:

I want to create gantt charts in python using create_gantt. However I have issues when I have overlapping start and end dates.

Eg:

import plotly.plotly as py

import plotly.figure_factory as ff

import plotly


df = [dict(Task="Milestone A", Start='2017-01-01', Finish='2017-02-02', Resource='Jack'),
      dict(Task="Milestone B", Start='2018-01-01', Finish='2018-02-02', Resource='Jack'),
      dict(Task="Milestone A", Start='2017-01-17', Finish='2017-04-28', Resource='Joe'),
      dict(Task="Milestone B", Start='2017-03-17', Finish='2017-04-28', Resource='Joe'),
      dict(Task="Milestone A", Start='2017-01-14', Finish='2017-03-14', Resource='John'),
      dict(Task="Milestone B", Start='2018-01-14', Finish='2018-03-14', Resource='John')]



colors = {'Jack': 'rgb(220, 0, 0)',
          'Joe': (1, 0.9, 0.16),
          'John': 'rgb(0, 255, 100)'}



fig = ff.create_gantt(df, colors=colors, index_col='Resource', show_colorbar=True, group_tasks=True)

plotly.offline.plot(fig, filename='gantt-group-tasks-together')

When I run this code, The bar lines for Joe, Jack and John overlap for Milestone A and Milestone B as in the figure. Bad Output I would like to see 3 lines for Milestone A for Joe, John and Jack clustered together but not overlapped like this

How do I achieve this?Good Output

解决方案

How about altair-viz (docs)?

import pandas as pd
import numpy as np
import altair as alt
# alt.renderers.enable('notebook') # if in jupyter

df = pd.read_csv("tasks.csv")
df["Start date"] = pd.to_datetime(df["Start date"])
df["End date"] = pd.to_datetime(df["End date"])

chart = alt.Chart(df.drop("Resources", 1)).mark_bar().encode(
    x='Start date',
    x2='End date',
    y=alt.Y('Task Name', 
            sort=list(df.sort_values(["End date", "Start date"])
                                    ["Task Name"])), # Custom sorting
)

chart

Example df:

-  -----------------------------------  -------------------  -------------------  ---------------------------------
0  Data type handling / Auto Inference  2019-07-01 00:00:00  2019-07-31 00:00:00  Backend
1  Sklearn & other models               2019-07-01 00:00:00  2019-07-31 00:00:00  Models
2  Maps / Geoplotting                   2019-07-01 00:00:00  2019-07-31 00:00:00  Backend, Graphical User Interface
3  Optimize Dockerfile                  2019-07-01 00:00:00  2019-07-31 00:00:00  CI/CD
4  Chapter 2: Compare competitors       2019-07-08 00:00:00  2019-10-21 00:00:00  Writing
-  -----------------------------------  -------------------  -------------------  ---------------------------------

Edit: I also found a way to add text and make it appear as if it has a progress bar. It works by creating another series whose bars have height equal to original * progress and appending it to the original dataframe

# Use the progress to find how much of the bars should be filled
# (i.e. another end date)
df["progress date"] =  (df["End date"] - df["Start date"]) * df["Progress %"] / 100 + df["Start date"]

# Concatenate the two 
newdf = np.concatenate([df[["Task Name", "Start date", "End date", "Progress %"]].values,  
                        df[["Task Name", "Start date", "progress date", "Progress %"]].values])
newdf = pd.DataFrame(newdf, columns=["Task Name", "Start date", "End date", "Progress %"])

# Reconvert back to datetime
newdf["Start date"] = pd.to_datetime(newdf["Start date"])
newdf["End date"] = pd.to_datetime(newdf["End date"])

# This is the indicator variable (duration vs progress) where the grouping takes place
newdf["progress_"] = np.concatenate([np.ones(len(newdf)//2), np.zeros(len(newdf)//2), ])

# color for first half, color for second half
range_ = ['#1f77b4', '#5fa0d4',]

# The stacked bar chart will be our "gantt with progress"
chart = alt.Chart(newdf).mark_bar().encode(
    x=alt.X('Start date', stack=None),
    x2='End date',
    y=alt.Y('Task Name', sort=list(df.sort_values(["End date",
                                                      "Start date"])["Task Name"])*2),
    color=alt.Color('progress_', scale=alt.Scale(range=range_), legend=None)
) 

# Create appropriate labels
newdf["text%"] = newdf["Progress %"].astype(str) + " %"

# And now add those as text in the graph
text = alt.Chart(newdf).mark_text(align='left', baseline='middle', dx=5, color="white",  fontWeight="bold").encode(
    y=alt.Y('Task Name', sort=list(df.sort_values(["End date",
                                                      "Start date"])["Task Name"])*2),
    x=alt.X('Start date'),
    text='text%',
)

# Plot the graph
alt.layer(chart, text)

Result:

这篇关于有没有办法在python中创建甘特图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆