Как составить гистограмму времени панд за определенный промежуток времени?

Я хочу построить некоторые даты и указать временной интервал, чтобы связать их вместе и создать гистограмму. Так, например, если в промежутке одного часа случается n datetime, сгруппируйте их или проанализируйте как год, месяц, день, час. И пропустите минуты и секунды. Допустим, у меня есть фрейм данных с некоторыми значениями даты и времени:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

date_today = datetime.now()
days = pd.date_range(date_today, date_today + timedelta(7), freq='D')

np.random.seed(seed=1111)
data = np.random.randint(1, high=100, size=len(days))
df = pd.DataFrame({'test': days, 'col2': data})
df = df.set_index('test')
print(df)

2018-06-19 17:10:32.076646    29
2018-06-20 17:10:32.076646    56
2018-06-21 17:10:32.076646    82
2018-06-22 17:10:32.076646    13
2018-06-23 17:10:32.076646    35
2018-06-24 17:10:32.076646    53
2018-06-25 17:10:32.076646    25
2018-06-26 17:10:32.076646    23

В идеале я хотел бы указать более гибкий временной интервал, например, "6 часов", чтобы выполнить какую-то операцию по модулю для datetime. Это возможно?

1 ответ

Решение

pd.Grouper

Позволяет указать регулярные интервалы частот, с которыми вы будете группировать свои данные. использование groupby затем объединить ваши df на основе этих групп. Например, если col2 было подсчитано, и вы хотели собрать все подсчеты за 2-дневные интервалы, вы можете сделать:

import pandas as pd
df.groupby(pd.Grouper(level=0, freq='2D')).col2.sum()

Выходы:

test
2018-06-19 13:49:11.560185    85
2018-06-21 13:49:11.560185    95
2018-06-23 13:49:11.560185    88
2018-06-25 13:49:11.560185    48
Name: col2, dtype: int32

Вы группируете по level=0твой индекс помечен 'test' и сумма col2 более 2 дней Поведение pd.Grouper может быть немного раздражающим, так как в этом примере корзины начинаются и заканчиваются в 13:49:11..., что, вероятно, не то, что вы хотите.

pd.cut + pd.date_range

У вас есть немного больше контроля над определением ваших корзин, если вы определяете их с помощью pd.date_range а затем использовать pd.cut, Здесь, например, вы можете определить корзины каждые 2 дня, начиная с 19-го.

df.groupby(pd.cut(df.index, 
                  pd.date_range('2018-06-19', '2018-06-27', freq='2D'))).col2.sum()

Выходы:

(2018-06-19, 2018-06-21]    85
(2018-06-21, 2018-06-23]    95
(2018-06-23, 2018-06-25]    88
(2018-06-25, 2018-06-27]    48
Name: col2, dtype: int32

Это хорошо, потому что если вы хотите, чтобы корзины начинались в четные дни, вы можете просто изменить даты начала и окончания в pd.date_range

df.groupby(pd.cut(df.index, 
                  pd.date_range('2018-06-18', '2018-06-28', freq='2D'))).col2.sum()

Выходы:

(2018-06-18, 2018-06-20]     29
(2018-06-20, 2018-06-22]    138
(2018-06-22, 2018-06-24]     48
(2018-06-24, 2018-06-26]     78
(2018-06-26, 2018-06-28]     23
Name: col2, dtype: int32

Если вы действительно хотите, вы можете указать 2,6-часовой цикл, начиная с 19 июня 2018 года в 5 часов утра:

df.groupby(pd.cut(df.index, 
                  pd.date_range('2018-06-19 5:00:00', '2018-06-28 5:00:00', freq='2.6H'))).col2.sum()
#(2018-06-19 05:00:00, 2018-06-19 07:36:00]     0
#(2018-06-19 07:36:00, 2018-06-19 10:12:00]     0
#(2018-06-19 10:12:00, 2018-06-19 12:48:00]     0
#(2018-06-19 12:48:00, 2018-06-19 15:24:00]    29
#....

Гистограмма.

Просто используйте .plot(kind='bar') после того, как вы агрегировали данные.

(df.groupby(pd.cut(df.index, 
                   pd.date_range('2018-06-19', '2018-06-28', freq='2D')))
   .col2.sum().plot(kind='bar', color='firebrick', rot=30))

введите описание изображения здесь

Другие вопросы по тегам