matplotlib x轴为24小时的条形图,日期时间数据仅为本节开头

uajslkp6  于 2023-10-24  发布在  其他
关注(0)|答案(1)|浏览(110)

我想画一个条形图(或直方图,但不是其他图),使x值对应于时间段,但x轴标签是从00:00到23:59,间隔为半小时。
问题出在我的框架中:列[“StartTime”]中的值是“datetime.time”类型,看起来像

0    00:30:00

1    06:00:00

2    07:00:00

3    09:10:00

4    15:30:00

5    18:00:00

6    19:00:00

“Main Street绿色(s”)“是相应的值。例如:

0     NaN

1    13.5

2    25.5

3    50.5

4    55.5

5    20.5

6    38.5

我希望00:00到00:30的条形图的高度为0,00:30到06:00的条形图的高度为13.5,06:30到07:00的条形图的高度为25.5。
我看过很多线图。https://www.programcreek.com/python/example/61484/matplotlib.dates.HourLocator是我发现的最有价值的资源

plt.rcParams['figure.figsize'] = (8.0, 6.0)
ax = plt.subplot(111)
ax.plot(Dayton_weekday["Start Time"], Dayton_weekday['Main Street Green (s)'], color = 'blue', label="main street")
#set ticks every half an hour
ax.xaxis.set_major_locator(mdates.HourLocator(byhour=range(0,24,48))) 
#set major ticks format
ax.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
ax.set_xlim(["00:00", "23:59"])
ax.set_ylim(bottom=0)

在我的代码中,我使用ax.plot,这是因为如果我使用ax.bar“ValueError:microsecond must be in 0..999999”将返回,所以我不知道如何使用我拥有的数据绘制条形图

2jcobegt

2jcobegt1#

这里有一个方法,应该给你给予你正在寻找的东西。

import datetime as dt
import matplotlib.pyplot as plt
import numpy as np

手动创建我们要绘制的时间。在您的数据集中,列出的时间与前一个条形图的结束时间相对应。为了适应条形图经过午夜的情况,将时间与条形图的开始时间相对应可能更容易。在下面的代码中,我修改了您的原始数据集以使用这种方法。列表中的第一个时间将是图的x轴上列出的第一个时间。

times = [dt.time(0,30,0),
         dt.time(6,0,0),
         dt.time(7,0,0),
         dt.time(9,10,0),
         dt.time(15,30,0),
         dt.time(18,0,0),
         dt.time(19,0,0)]

与其在x轴上绘制dt.time(),不如绘制一天中经过的秒数。下面我们使用列表解析将times转换为经过的秒数。

seconds = [(x.hour * 3600 + x.minute * 60 + x.second)
           for x in times]

注意事项:我删除了values开头的NaN,并在结尾添加了一个虚构的5.5,以便显示从19:00到0:30的条形图。

# manually add the y-axis values
values = [13.5,
          25.5,
          50.5,
          55.5,
          20.5,
          38.5,
          5.5]

现在,我们创建两个列表,用于指定刻度在x轴上的位置,以及为每个刻度分配什么标签。(30分钟),start_time将是times中第一个项目经过的秒数。这是x-轴将开始。

start_time = (times[0].hour * 3600 + times[0].minute * 60 + times[0].second)
xticks = [x + start_time for x in range(60 * 60 * 24) if x % 1800 == 0]

为了显示时间而不是经过的秒数,我们必须使用dt.timedelta()将整数转换为dt.time。如果start_time是大于0的值,则会有xticks,其值至少为86400。我们必须从这些值中减去86400,以防止xticklabels显示为one day, 0:30

def label_format(seconds):
    if seconds >= 86400:
        seconds -= 86400

    return str(dt.timedelta(seconds=seconds))

xticklabels = [label_format(x) for x in xticks]

现在我们可以创建图了。由于我们要创建一个条形宽度不等的直方图样式的图表,我们需要一种方法来指定条形宽度。bar_traits()可以用来根据x轴的起点和下一个条形的起点来确定条形的起点和宽度。

def bar_traits(ix, second, seconds, start_time):
    if ix < len(seconds) - 1:
        if seconds[ix + 1] < second:
            width = 86400 + seconds[ix + 1] - second
        else:
            width = seconds[ix + 1] - second
    else:
        if start_time < second:
            width = 86400 + start_time - second
        else:
            width = start_time - second
    if start_time > second:
        second += 86400

    return second, width

使用bar_traits()创建绘图的代码,以处理跨午夜的绘图。

fig, ax = plt.subplots(figsize=(16,8))

for ix, (second, value) in enumerate(zip(seconds, values)):
    second, width = bar_traits(ix, second, seconds, start_time)
    ax.bar(second, value, width=width, align='edge', color='C0')

ax.set_xticks(xticks)
ax.set_xticklabels(xticklabels, rotation=90)

plt.show()

相关问题