我一直在努力帮助我的妻子,她每天都在跟踪她的每一个客户的时间,通过想象她每天花在工作上的时间被客户所渲染。
下面是我试图用Python实现的一个例子(在Excel中构建以供参考,代码包含示例数据)。

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图形更简单的解决方案。
发布于 2020-06-14 20:28:35
我以前还没有试着画出这样的代码,所以代码肯定会更好。话虽如此,以下是我所取得的成就:

首先,您需要导入一些包:
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数组:
data = np.array(data)[1:, :]之后,我们需要在一个排序列表中获得所有唯一的日子,并使用以下方法制作字典:
days_list = sorted(list(set([date[:10] for date in data[:, 2]])))[::-1]
days = { day: i+1 for i, day in enumerate(days_list) }然后,基于客户端进行协同工作:
clients = sorted(list(set(data[:, 0])))
colormapping = { client: f"C{i}" for i, client in enumerate(clients) }作为最后的设置,我们需要保存每个条目的开始和结束时间:
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]]现在,我们可以遍历所有数据点,并为此添加一个顶点、颜色和文本位置:
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内容:
# 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()您可以在这个吉特布·吉斯特中查看完整代码。
https://stackoverflow.com/questions/62376753
复制相似问题