使用 python 和 matplotlib 的时间线条形图
Posted
技术标签:
【中文标题】使用 python 和 matplotlib 的时间线条形图【英文标题】:Timeline bar graph using python and matplotlib 【发布时间】:2019-01-01 11:16:32 【问题描述】:我希望使用 matplotlib 绘制一个时间线条形图,该条形图将显示一个人在一天内所做的事情。我正在添加下面的代码、输出和我正在寻找的预期输出。可以使用任何库,在我的情况下,我可以使用的壁橱使用 matplotlib。任何帮助将不胜感激。
import datetime as dt
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
data = [ (dt.datetime(2018, 7, 17, 0, 15), dt.datetime(2018, 7, 17, 0, 30), 'sleep'),
(dt.datetime(2018, 7, 17, 0, 30), dt.datetime(2018, 7, 17, 0, 45), 'eat'),
(dt.datetime(2018, 7, 17, 0, 45), dt.datetime(2018, 7, 17, 1, 0), 'work'),
(dt.datetime(2018, 7, 17, 1, 0), dt.datetime(2018, 7, 17, 1, 30), 'sleep'),
(dt.datetime(2018, 7, 17, 1, 15), dt.datetime(2018, 7, 17, 1, 30), 'eat'),
(dt.datetime(2018, 7, 17, 1, 30), dt.datetime(2018, 7, 17, 1, 45), 'work')
]
rng=[]
for i in range(len(data)):
rng.append((data[i][0]).strftime('%H:%M'))
index=
activity = []
for i in range(len(data)):
index[(data[i][2])]=[]
activity.append(data[i][2])
for i in range(len(index)):
for j in range(len(activity)):
if activity[j]==index.keys()[i]:
index[index.keys()[i]].append(15)
else:
index[index.keys()[i]].append(0)
data = list(index.values())
df = pd.DataFrame(data,index=list(index.keys()))
df.plot.barh(stacked=True, sharex=False)
plt.show()
我的输出:
使用 matplotlib 这就是我得到的
预期输出:
我使用谷歌图表时间线图得到了这个,但我需要这个使用 python 并且用于生成两个图表的数据不完全相同,我希望你明白这一点
【问题讨论】:
你的代码有问题@index[(data[i][3])]=[] 【参考方案1】:您可以创建一个PolyCollection
的“酒吧”。为此,您需要将日期转换为数字 (matplotlib.dates.date2num
)。
import datetime as dt
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.collections import PolyCollection
data = [ (dt.datetime(2018, 7, 17, 0, 15), dt.datetime(2018, 7, 17, 0, 30), 'sleep'),
(dt.datetime(2018, 7, 17, 0, 30), dt.datetime(2018, 7, 17, 0, 45), 'eat'),
(dt.datetime(2018, 7, 17, 0, 45), dt.datetime(2018, 7, 17, 1, 0), 'work'),
(dt.datetime(2018, 7, 17, 1, 0), dt.datetime(2018, 7, 17, 1, 30), 'sleep'),
(dt.datetime(2018, 7, 17, 1, 15), dt.datetime(2018, 7, 17, 1, 30), 'eat'),
(dt.datetime(2018, 7, 17, 1, 30), dt.datetime(2018, 7, 17, 1, 45), 'work')
]
cats = "sleep" : 1, "eat" : 2, "work" : 3
colormapping = "sleep" : "C0", "eat" : "C1", "work" : "C2"
verts = []
colors = []
for d in data:
v = [(mdates.date2num(d[0]), cats[d[2]]-.4),
(mdates.date2num(d[0]), cats[d[2]]+.4),
(mdates.date2num(d[1]), cats[d[2]]+.4),
(mdates.date2num(d[1]), cats[d[2]]-.4),
(mdates.date2num(d[0]), cats[d[2]]-.4)]
verts.append(v)
colors.append(colormapping[d[2]])
bars = PolyCollection(verts, facecolors=colors)
fig, ax = plt.subplots()
ax.add_collection(bars)
ax.autoscale()
loc = mdates.MinuteLocator(byminute=[0,15,30,45])
ax.xaxis.set_major_locator(loc)
ax.xaxis.set_major_formatter(mdates.AutoDateFormatter(loc))
ax.set_yticks([1,2,3])
ax.set_yticklabels(["sleep", "eat", "work"])
plt.show()
请注意,同样可以使用 Broken Bar plot (broken_barh
) 生成此类图,但是,此处使用的(未排序的)数据使用 PolyCollection 会更容易一些。
现在你需要向我解释你是如何同时睡觉和吃饭的——这是我永远无法做到的,尽管我尽力了。
【讨论】:
哈哈,当我看到添加了新的答案时,我立刻就知道是你。 感谢您的回答,这是您在回答末尾指出的数据中的一个错误,这就是我添加预期输出以防我的代码出现任何错误的原因或问题 所以我们可以像上面的示例输出中那样更改 x 轴,例如 1,2,3..24 小时或 2,4..24,并根据它绘制图表,以便它全天数据多时不笨拙? 当然,您可以使用任何您喜欢的定位器和格式化程序。可能HourLocator
有意义,DateFormatter("%H")
。
睡觉是我过去最喜欢的时间。【参考方案2】:
我使用 Altair 的解决方案 (example):
import altair as alt
import datetime as dt
import pandas as pd
alt.renderers.enable('jupyterlab')
data = pd.DataFrame()
data['from'] = [dt.datetime(2018, 7, 17, 0, 15),
dt.datetime(2018, 7, 17, 0, 30),
dt.datetime(2018, 7, 17, 0, 45),
dt.datetime(2018, 7, 17, 1, 0),
dt.datetime(2018, 7, 17, 1, 15),
dt.datetime(2018, 7, 17, 1, 30)]
data['to'] = [dt.datetime(2018, 7, 17, 0, 30),
dt.datetime(2018, 7, 17, 0, 45),
dt.datetime(2018, 7, 17, 1, 0),
dt.datetime(2018, 7, 17, 1, 15),
dt.datetime(2018, 7, 17, 1, 30),
dt.datetime(2018, 7, 17, 1, 45)]
data['activity'] = ['sleep','eat','work','sleep','eat','work']
#data
alt.Chart(data).mark_bar().encode(
x='from',
x2='to',
y='activity',
color=alt.Color('activity', scale=alt.Scale(scheme='dark2'))
)
输出:
【讨论】:
以上是关于使用 python 和 matplotlib 的时间线条形图的主要内容,如果未能解决你的问题,请参考以下文章
如何在ubuntu上使用pip为python3升级matplotlib?