Как построить гистограмму, сгруппированную по двум переменным

#python #pandas #dataframe #datetime #matplotlib

Вопрос:

У меня есть данные о 15-минутном временном шаге за несколько лет…

Дата и время Количество
01/07/2018 00:15 6.96
01/07/2018 00:30 6.48
01/07/2018 00:45 6.96
01/07/2018 01:00 6.72
. .
. .

Я использую Панд. Как мне создать столбиковую диаграмму с месяцами на горизонтальной оси; и серию (набор столбиков) для каждого года; высота каждого столбика-общее количество за этот месяц и год.

Точно так же, как это:

примерный сюжет

Ответ №1:

Создание поддельного фрейма данных:

 df = pd.DataFrame()
df['Datetime'] = pd.date_range(start = '01/07/2018', end = '13/08/2021', freq = '15min')
df['Quantity'] = np.random.rand(len(df))
 

Начиная с этого момента, вы должны извлечь месяц и год и сохранить их в отдельных столбцах:

 df['month'] = df['Datetime'].dt.month
df['year'] = df['Datetime'].dt.year
 

Затем вы должны рассчитать сумму 'Quantity' по месяцам за каждый год:

 df = df.groupby(by = ['month', 'year'])['Quantity'].sum().reset_index()
 

После этого отрывка у вас должен быть такой фрейм данных, как этот:

              Datetime  Quantity  month  year
0 2018-01-07 00:00:00  0.226113      1  2018
1 2018-01-07 00:15:00  0.222872      1  2018
2 2018-01-07 00:30:00  0.835484      1  2018
3 2018-01-07 00:45:00  0.775771      1  2018
4 2018-01-07 01:00:00  0.972559      1  2018
5 2018-01-07 01:15:00  0.418036      1  2018
6 2018-01-07 01:30:00  0.902843      1  2018
7 2018-01-07 01:45:00  0.012441      1  2018
8 2018-01-07 02:00:00  0.883437      1  2018
9 2018-01-07 02:15:00  0.183561      1  2018
 

Теперь кадр данных готов к построению; с помощью seaborn:

 fig, ax = plt.subplots()

sns.barplot(ax = ax, data = df, x = 'month', y = 'Quantity', hue = 'year')

plt.show()
 

Полный Код

 import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns


df = pd.DataFrame()
df['Datetime'] = pd.date_range(start = '01/07/2018', end = '13/08/2021', freq = '15min')
df['Quantity'] = np.random.rand(len(df))
df['month'] = df['Datetime'].dt.month
df['year'] = df['Datetime'].dt.year

df = df.groupby(by = ['month', 'year'])['Quantity'].sum().reset_index()


fig, ax = plt.subplots()

sns.barplot(ax = ax, data = df, x = 'month', y = 'Quantity', hue = 'year')

plt.show()
 

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

Ответ №2:

Возможно, вы можете извлечь месяцы и годы в новые столбцы и сделать несколько подзаголовков с месяцами по оси x, по одному на каждый год, и объединить их все в конце в уникальный график. Взгляните на пример ниже и обратите внимание на параметр ширины и смещение на одно и то же значение plt.bar , чтобы графики не перекрывали друг друга.

 import pandas as pd
import matplotlib.pyplot as plt
import datetime

# create df
d1 = datetime.date(2018, 8, 30)
d2 = datetime.date(2018, 9, 30)
d3 = datetime.date(2019, 8, 30)
d4 = datetime.date(2019, 9, 30)

df = pd.DataFrame({
    'date': [d1, d1, d2, d2, d3, d3, d4, d4],
    'values':[10, 20, 40, 40, 50, 55, 65, 70]})

df['month'] = df.date.apply(lambda x: x.month)
df['year'] = df.date.apply(lambda x: x.year)

# make plots
fig, ax = plt.subplots()
ax = plt.bar(df[df.year == 2018].groupby(['month']).sum()['values'].index, df[df.year == 2018].groupby(['month']).sum()['values'])
ax = plt.bar(df[df.year == 2019].groupby(['month']).sum()['values'].index, df[df.year == 2019].groupby(['month']).sum()['values'])
plt.show()
 

Возможно, создание новых столбцов, как это сделал я, будет не очень эффективным для вас, если у вас очень большой фрейм данных. Чтобы построить графики, я отфильтровал строки по годам в каждой строке, сгруппировал их по месяцам и использовал сумму значений. Индексы представляют собой кортежи (year, month) .