0

I'm trying to build a Gantt chart in Python (indifferent to package used... perhaps Plotly?) where the X-axis will be discrete dates (e.g., 2020-01-01, 2020-01-02, ...) and the Y-axis will be names (e.g., 'A', 'B', ...). The lists of dates per name aren't necessarily contiguous. They are currently in the following format:

names_dict = {
              'A': ['2020-01-01', '2020-01-02', '2020-01-31'], 
              'B': ['2020-01-03'], 
              'C': ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04'],
              ...
              }

Is there an easy way to build a Gantt-type chart from a dictionary in this format? Ideally it would be a grid, and for each date on the X-axis the square for a given name would either be white or red (indicating the presence of that date in the list of dates for that name). Thus, the dates on the X-axis would be the continuous range from the earliest date present in any list in the dictionary to the latest date.

OJT
  • 887
  • 1
  • 10
  • 26
  • Quite some ideas in the answers to [this post](https://stackoverflow.com/questions/52432281/how-to-plot-a-diagram-like-this-in-matplot-python/). There is also [this other post](https://stackoverflow.com/questions/56803727/how-to-get-gantt-plot-using-matplotlib-for-task-with-start-time-and-end-time-upt) and [this article](https://sukhbinder.wordpress.com/2016/05/10/quick-gantt-chart-with-matplotlib/). – JohanC Jan 08 '20 at 22:35
  • @JohanC these seem to refer to continuous Gantt charts (with a single start date and end date per row) -- any ideas on how to make a discontinuous one? – OJT Jan 09 '20 at 01:14

1 Answers1

0

Here is an example using the given data with matplotlib's horizontal bars (barh). The dictionary is traversed in reverse order of the keys, as matplotlib draws them starting at the bottom.

Matplotlib allows a myriad of tweeking, for every aspect of the plot.

from matplotlib import pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime

names_dict = {'A': ['2020-01-01', '2020-01-02', '2020-01-31'],
              'B': ['2020-01-03'],
              'C': ['2020-01-01', '2020-01-02', '2020-01-03', '2020-01-04'] }

# x_min = min([datetime.fromisoformat(d) for dates in names_dict.values() for d in dates])

fig, ax = plt.subplots(figsize=(12,4))
for name in reversed(list(names_dict.keys())):
    for d in names_dict[name]:
        ax.barh(name, width=1.0, left=mdates.date2num(datetime.fromisoformat(d)),
                height=1.0, color='crimson', align='center')
for i in range(len(names_dict)+1):
    ax.axhline(i-0.5, color='black')

ax.xaxis_date()
ax.xaxis.set_minor_locator(mdates.DayLocator(interval=1))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=5))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%b %d"))
# ax.grid(True, axis='x') # to show vertical gridlines at each major tick
ax.autoscale(enable=True, axis='y', tight=True)
plt.show()

resulting plot

JohanC
  • 71,591
  • 8
  • 33
  • 66