【问题标题】:Timeline bar graph using python and matplotlib使用 python 和 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])]=[]

标签: python-2.7 pandas numpy matplotlib


【解决方案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'))
)

输出:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 2017-03-27
    • 1970-01-01
    • 2017-10-18
    • 1970-01-01
    相关资源
    最近更新 更多