Диаграмма Ганта из словаря со списками дискретных несмежных дат в качестве значений - PullRequest
0 голосов
/ 09 января 2020

Я пытаюсь построить диаграмму Ганта в Python (безразлично к используемому пакету ... возможно, в графике?), Где по оси X будут дискретные даты (например, 2020-01-01, 2020-01- 02, ...) и ось Y будет именами (например, 'A', 'B', ...). Списки дат по имени не обязательно являются смежными. В настоящее время они имеют следующий формат:

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 квадрат для данного имени будет либо белым, либо красным (что указывает на наличие этой даты в списке дат для этого имени). Таким образом, даты на оси X будут представлять собой непрерывный диапазон от самой ранней даты, присутствующей в любом списке в словаре, до самой последней даты.

1 Ответ

0 голосов
/ 09 января 2020

Вот пример использования данных с горизонтальными столбцами matplotlib (barh). Словарь перебирается в обратном порядке клавиш, так как matplotlib dr aws они начинаются снизу.

Matplotlib позволяет выполнять множество операций по настройке для каждого аспекта графика.

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

...