Постройте годовые данные с датой месяца по оси X

У меня есть фрейм данных Pandas, содержащий ежедневные данные для переменной за 3 года. Мне нужно построить линейную диаграмму, где ось X составляет от 1/1 до 12/31 (только месяц и день, без года) и имеет 3 линии, по одной для каждого года. Как мне построить это в matplotlib?

        DateTime    price
10      2007-10-06  35756.0
11      2007-10-06  34747.0
12      2007-10-07  35748.0
13      2007-10-07  34743.0
14      2007-10-08  35740.0
... ... ...
1519    2009-10-29  29564.0
1520    2009-10-30  32035.0
1521    2009-10-30  29397.0
1522    2009-10-31  32003.0
1523    2009-10-31  29256.0

Для приведенных выше данных мне нужно, чтобы на оси X были даты от 1/1 до 31 декабря и 3 строки, по одной для 2007, 2008 и 2009 годов.

Пожалуйста, предоставьте минимальный воспроизводимый пример данных.

mozway 07.03.2024 05:12
1
1
57
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

1- использование строк месяца и дня для оси X

Вы можете извлечь год и месяц-день (с помощью strftime ), затем сводную точку и график:

import pandas as pd
import numpy as np

# create a dummy dataset
df = pd.DataFrame({'DateTime': pd.date_range('2020-01-01', '2022-12-31'),
                   'price': np.sin(np.arange(1096)/80)
                  })

# if needed, ensure we have datetime
df['DateTime'] = pd.to_datetime(df['DateTime'])

# create new columns with year and month-day
# pivot and plot
(df.assign(year=lambda d: d['DateTime'].dt.year,
           day=lambda d: d['DateTime'].dt.strftime('%m-%d')
          )
   .pivot(index='day', columns='year', values='price')
   .plot()
)

Выход:

Вариант с seaborn.lineplot:

import seaborn as sns
import matplotlib.ticker as ticker

ax = sns.lineplot(data=df, x=df['DateTime'].dt.strftime('%m-%d'), y='price',
                  hue=df['DateTime'].dt.year)

ax.xaxis.set_major_locator(ticker.LinearLocator(10))

Выход:

Временной ряд с извлеченными годом и месяцем-днем:

       DateTime     price  year    day
0    2020-01-01  0.000000  2020  01-01
1    2020-01-02  0.012500  2020  01-02
2    2020-01-03  0.024997  2020  01-03
3    2020-01-04  0.037491  2020  01-04
4    2020-01-05  0.049979  2020  01-05
...         ...       ...   ...    ...
1091 2022-12-27  0.877742  2022  12-27
1092 2022-12-28  0.883663  2022  12-28
1093 2022-12-29  0.889445  2022  12-29
1094 2022-12-30  0.895088  2022  12-30
1095 2022-12-31  0.900592  2022  12-31

[1096 rows x 4 columns]

2- использование реальной оси X даты и времени с общим годом, а затем изменение форматирования

Другой вариант, который мог бы быть более удобным, — это установить общий високосный год (например, 2000) для построения графиков с использованием красивых отметок MonthLocator, а затем изменить формат, чтобы скрыть год:

import matplotlib.dates as mdates

ax = (df
   .assign(year=lambda d: d['DateTime'].dt.year,
           day=lambda d: d['DateTime'].add(pd.DateOffset(year=2000))
          )
   .pivot(index='day', columns='year', values='price')
   .plot()
)

# add a tick for each month
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
# change the format to the month name
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))

Выход:

Та же логика с seaborn:

import seaborn as sns
import matplotlib.dates as mdates

ax = sns.lineplot(data=df, x=df['DateTime'].add(pd.DateOffset(year=2000)),
                  y='price', hue=df['DateTime'].dt.year)

ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))

Выход:

Примечание. На всех графиках вы можете заметить небольшой разрыв в данных между 28 февраля и 1 марта для 2021 и 2022 годов, поскольку это не високосные годы.

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