使用 python 和 matplotlib 的时间线条形图

Posted

技术标签:

【中文标题】使用 python 和 matplotlib 的时间线条形图【英文标题】:Timeline bar graph using python and matplotlib 【发布时间】:2019-01-01 11:16:32 【问题描述】:

我希望使用 ma​​tplotlib 绘制一个时间线条形图,该条形图将显示一个人在一天内所做的事情。我正在添加下面的代码、输出和我正在寻找的预期输出。可以使用任何库,在我的情况下,我可以使用的壁橱使用 ma​​tplotlib。任何帮助将不胜感激。

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 的时间线条形图的主要内容,如果未能解决你的问题,请参考以下文章

在安卓上使用 python 和 matplotlib

python matplotlib数据作图

如何在ubuntu上使用pip为python3升级matplotlib?

Python使用matplotlib可视化饼图为饼图添加标题和标签(Pie Chart)

python matplotlib数据作图

第92天:Python Matplotlib 进阶操作