гистограмма с 24 часами по оси x с данными даты и времени только начала этого раздела - PullRequest
1 голос
/ 24 сентября 2019

Я хочу нарисовать гистограмму (или гистограмму, но не другой график) так, чтобы значение x соответствовало периоду времени, а метка оси x была от 00:00 до 23:59 с интервалом в полчаса.

Проблема в моем фрейме данных: значение в столбце ["Время начала"] имеет тип "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 Green (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: микросекунда должна быть в 0..999999 "будет возвращено, поэтому я не знаю, как нарисовать гистограмму, используя данные, которые у меня есть

1 Ответ

0 голосов
/ 25 сентября 2019

Вот подход, который должен дать вам то, что вы ищете.

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)]

Вместо того, чтобы наносить dt.time() на оси X, может быть проще построить графикколичество секунд, прошедших за день.Ниже мы используем понимание списка, чтобы преобразовать times в число прошедших секунд.

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

Примечание: я удалил NaN в начале values и добавил вымышленный 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 находитсяТики должны быть размещены, и какой ярлык назначить каждому из этих тиков.Если количество прошедших секунд делится на 1800 (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()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...