首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在一个日期上创建一个具有多个起始点和结束点的条形图?

如何在一个日期上创建一个具有多个起始点和结束点的条形图?
EN

Stack Overflow用户
提问于 2020-06-14 18:40:41
回答 1查看 212关注 0票数 1

我一直在努力帮助我的妻子,她每天都在跟踪她的每一个客户的时间,通过想象她每天花在工作上的时间被客户所渲染。

下面是我试图用Python实现的一个例子(在Excel中构建以供参考,代码包含示例数据)。

代码语言:javascript
复制
data = [["Client", "Task", "Start Time", "End Time"],
    ["client-A", "task-a", "2020-06-10 11:10", "2020-06-10 11:25"],
    ["client-B", "task-b", "2020-06-10 11:30", "2020-06-10 13:54"],
    ["client-B", "task-a", "2020-06-10 17:34", "2020-06-10 18:00"],
    ["client-D", "task-e", "2020-06-11 08:05", "2020-06-11 12:45"],
    ["client-C", "task-d", "2020-06-11 15:15", "2020-06-11 17:01"],
    ["client-A", "task-a", "2020-06-11 19:10", "2020-06-11 20:18"],
    ["client-A", "task-c", "2020-06-11 20:18", "2020-06-11 21:36"],
    ["client-C", "task-a", "2020-06-12 08:02", "2020-06-12 08:25"],
    ["client-D", "task-e", "2020-06-12 08:45", "2020-06-12 09:55"],
    ["client-E", "task-d", "2020-06-12 10:00", "2020-06-12 11:07"],
    ["client-B", "task-c", "2020-06-12 11:11", "2020-06-12 12:30"]]

df = pd.DataFrame(data[1:], columns=data[0])

谢谢您的帮助,我希望有一个比手工Excel图形更简单的解决方案。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-14 20:28:35

我以前还没有试着画出这样的代码,所以代码肯定会更好。话虽如此,以下是我所取得的成就:

首先,您需要导入一些包:

代码语言:javascript
复制
import numpy as np
import datetime as dt

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.collections import PolyCollection
import matplotlib.patches as mpatches

我冒昧地将头从数据数组中移除并将其转换为numpy数组:

代码语言:javascript
复制
data = np.array(data)[1:, :]

之后,我们需要在一个排序列表中获得所有唯一的日子,并使用以下方法制作字典:

代码语言:javascript
复制
days_list = sorted(list(set([date[:10] for date in data[:, 2]])))[::-1]
days = { day: i+1 for i, day in enumerate(days_list) }

然后,基于客户端进行协同工作:

代码语言:javascript
复制
clients = sorted(list(set(data[:, 0])))
colormapping = { client: f"C{i}" for i, client in enumerate(clients) }

作为最后的设置,我们需要保存每个条目的开始和结束时间:

代码语言:javascript
复制
start_times = [dt.datetime.strptime(date[11:], "%H:%M") for date in data[:, 2]]
end_times = [dt.datetime.strptime(date[11:], "%H:%M") for date in data[:, 3]]

现在,我们可以遍历所有数据点,并为此添加一个顶点、颜色和文本位置:

代码语言:javascript
复制
verts, colors, texts = [], [], []
for i, d in enumerate(data):
    client, task, date_str = d[0], d[1], d[2]
    day_num = days[date_str[:10]]
    start_date = mdates.date2num(start_times[i])
    end_date = mdates.date2num(end_times[i])

    v = [(start_date, day_num - .4),
         (start_date, day_num + .4),
         (end_date, day_num + .4),
         (end_date, day_num - .4),
         (start_date, day_num - .4)
    ]
    verts.append(v)
    colors.append(colormapping[client])
    texts.append((start_date, day_num, task[-1].upper()))

当您有了这个之后,它是基本的Matplotlib内容:

代码语言:javascript
复制
# Make PolyCollection and scale
bars = PolyCollection(verts, facecolors=colors, edgecolors=("black",))
fig, ax = plt.subplots()
ax.add_collection(bars)
ax.autoscale()

# Set ticks to show every 30 minutes and in specific format
xticks = mdates.MinuteLocator(byminute=[0, 30])
ax.xaxis.set_major_locator(xticks)
ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M"))
fig.autofmt_xdate()

# Set y-axis to be dates
ax.set_yticks(range(1, len(days_list) + 1))
ax.set_yticklabels(days_list)

# Add task text to plot
for (start_date, day_num, task) in texts:
    plt.text(start_date+.003, day_num-.03, task, color="w")

# Create legend based on clients
plt.legend(handles=[mpatches.Patch(color=color, label=client)
                    for client, color in colormapping.items()])

# Add grid and show
plt.grid()
plt.show()

您可以在这个吉特布·吉斯特中查看完整代码。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62376753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档