# How to make a gantt plot with Plots.jl

**URL:** <https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165>\
**Category:** General Usage\
**Tags:** question, plotting, plots\
**Created:** [February 24, 2023, 9:02pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165 "2023-02-24T21:02:28Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [February 24, 2023, 9:02pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/1 "2023-02-24T21:02:28Z")

</div>

Hi,

I would like to make a gantt plot in Plots.jl. I came across a few old posts concerning gantt plots, but no solution. Here is what I have so far:

```julia
using StatsPlots
using DataFrames

df = DataFrame(label=["A","B"],
                start_time = [1.0,3.0],
                end_time = [4.0, 5.0],
                color = [:blue, :green])

@df df bar(:start_time, yticks = (1:2,:label), orientation=:h, leg=false, color=:color)

```

The problem is that the y labels are backwards and the bars are not correctly displayed between the start time and end times. Any help would be greatly appreciated.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [February 25, 2023, 12:44am UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/2 "2023-02-25T00:44:19Z")

</div>

Using Plots.jl:

```julia
using Plots, DataFrames

rect(w, h, x, y) = Shape(x .+ [0,w,w,0], y .+ [0,0,h,h])

df = DataFrame(label=["A","B"], start_time=[1.0,3.0], end_time=[4.0,5.0], color=[:blue,:green])
df.duration = df.end_time - df.start_time
r = [rect(t[1],1,t[2],t[3]) for t in zip(df.duration, df.start_time, 1:nrow(df))]

plot(r, c=permutedims(df.color), yticks=(1.5:(nrow(df) + 0.5), df.label), xlabel="Time")

```

 ![Plots_Gantt_chart](https://global.discourse-cdn.com/julialang/original/3X/5/5/554ec7d95245ff53bb7ba23044b10e9a1b530f28.png)

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [February 25, 2023, 9:33am UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/3 "2023-02-25T09:33:31Z")

</div>

Thanks again Rafael! 🙂

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [February 25, 2023, 10:39am UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/4 "2023-02-25T10:39:44Z")

</div>

Fyi, I have updated the code according to the best practice of plotting performance: _plot all objects at once if possible._

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [February 25, 2023, 2:34pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/5 "2023-02-25T14:34:21Z")

</div>

Awesome. Much appreciated!

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [March 15, 2023, 12:58pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/6 "2023-03-15T12:58:38Z")

</div>

@rafael.guerra, I was hoping I could ask you a follow up question. How do I force all labels of the same type on to the same row. Here is a simple example:

```julia
using Plots, DataFrames

rect(w, h, x, y) = Shape(x .+ [0,w,w,0], y .+ [0,0,h,h])

df = DataFrame(label=["A","B","B"], start_time=[1.0,3.0,6.0], end_time=[4.0,5.0,8.0], color=[:blue,:green,:green])

df.duration = df.end_time - df.start_time

r = [rect(t[1],1,t[2],t[3]) for t in zip(df.duration, df.start_time, 1:nrow(df))]

plot(r, c=permutedims(df.color), yticks=(1.5:(nrow(df) + 0.5), df.label), xlabel="Time")

```

The problem is that two rows are created for B instead of 1. Any help would be greatly appreciated!

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 15, 2023, 1:30pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/7 "2023-03-15T13:30:37Z")

</div>

Hi Christopher, I am lacking time now, but please try the following:

```julia
using Plots, DataFrames

rect(w, h, x, y) = Shape(x .+ [0,w,w,0], y .+ [0,0,h,h])

df = DataFrame(label=["A","B","B"], start_time=[1.0,3.0,6.0], end_time=[4.0,5.0,8.0], color=[:blue,:green,:green])
df.duration = df.end_time - df.start_time
u = unique(df.label)
dy = Dict(u .=> 1:length(u))
r = [rect(t1, 1, t2, dy[t3]) for (t1,t2,t3) in zip(df.duration, df.start_time, df.label)]

plot(r, c=permutedims(df.color), yticks=(1.5:(nrow(df) + 0.5), df.label), xlabel="Time", labels=false)

```

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [March 15, 2023, 1:44pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/8 "2023-03-15T13:44:36Z")

</div>

Thanks for your help. I was able to remove the third empty row with the following code.

```julia
using Plots, DataFrames

rect(w, h, x, y) = Shape(x .+ [0,w,w,0], y .+ [0,0,h,h])

df = DataFrame(label=["A","B","B"], start_time=[1.0,3.0,6.0], end_time=[4.0,5.0,8.0], color=[:blue,:green,:green])

df.duration = df.end_time - df.start_time

nl = length(unique(df.label))

dy = Dict(unique(df.label) .=> 1:nl)

r = [rect(t[1],1,t[2], dy[t[3]]) for t in zip(df.duration, df.start_time, df.label)]

y_axis_labels = unique(df.label)

plot(r, c=permutedims(df.color), yticks=(1.5:(length(y_axis_labels) + 0.5), y_axis_labels), xlabel="Time", labels=false)

```

The only thing I need to do is figure how to enclose the boarder around the rectangles. For some reason the left border is missing. I’ll report back with an update if I find a solution.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [August 13, 2023, 10:08pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/9 "2023-08-13T22:08:15Z")

</div>

I never figured out how to enclose the border around the bars with the pyplot backend. I wanted to see if anyone has a solution for this problem. It works for gr, but I think pyplot + eps looks better.

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [August 14, 2023, 9:11am UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/11 "2023-08-14T09:11:14Z")

</div>

I tried that and `linecolor`. I believe they are aliases. In matplotlib it is called `edgecolor`, but I did not find any insights when searching for that keyword in the source code. Do you think it is a bug?

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [August 14, 2023, 1:29pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/12 "2023-08-14T13:29:51Z")

</div>

Sorry, I misread your message.

For some reason, the `pythonplot()` backend doesn’t actually close the rectangle. All you have to do is redefine the function:

```julia
rect(w, h, x, y) = Shape(x .+ [0,w,w,0,0], y .+ [0,0,h,h,0])

```

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [August 14, 2023, 3:45pm UTC](https://discourse.julialang.org/t/how-to-make-a-gantt-plot-with-plots-jl/95165/13 "2023-08-14T15:45:25Z")

</div>

> [@rafael.guerra](#):
>
> `Shape(x .+ [0,w,w,0,0], y .+ [0,0,h,h,0])`

I would not have guessed that as a solution. Thanks!
