matplotlib xticks выводит неверный массив

Я пытаюсь построить временной ряд, который выглядит так

ts
2020-01-01 00:00:00    1300.0
2020-01-01 01:00:00    1300.0
2020-01-01 02:00:00    1300.0
2020-01-01 03:00:00    1300.0
2020-01-01 04:00:00    1300.0
                        ...  
2020-12-31 19:00:00    1300.0
2020-12-31 20:00:00    1300.0
2020-12-31 21:00:00    1300.0
2020-12-31 22:00:00    1300.0
2020-12-31 23:00:00    1300.0
Freq: H, Name: 1, Length: 8784, dtype: float64

И я рисую это через: ts.plot(label=label, linestyle='--', color='k', alpha=0.75, zorder=2)

Если временной ряд ts начинается с 2020-01-01 до 2020-12-31, при вызове plt.xticks()[0] я получаю следующее:

array([438288, 439032, 439728, 440472, 441192, 441936, 442656, 443400,
       444144, 444864, 445608, 446328, 447071], dtype=int64)

что хорошо, поскольку первый элемент этого массива фактически показывает правильное положение первого xtick. Однако, когда я расширяю объект временного ряда с 2019-01-01 до 2020-12-31, то есть через 2 года, когда я вызываю plt.xticks()[0], я получаю следующее:

array([429528, 431688, 433872, 436080, 438288, 440472, 442656, 444864,
       447071], dtype=int64)

Я не понимаю, почему теперь я получаю меньше значений xticks. Итак за 12 месяцев я получаю 13 локаций для xticks. Но за 24 месяца я рассчитывал получить 25 локаций. Вместо этого я получил только 9. Как мне получить все эти 25 местоположений?

Это весь скрипт:

fig, ax = plt.subplots(figsize=(8,4))
ts.plot(label=label, linestyle='--', color='k', alpha=0.75, zorder=2)
locs, labels = plt.xticks()

person oakca    schedule 22.02.2021    source источник
comment
Какая разница в масштабе? Бьюсь об заклад, второй участок имеет клещей каждые 3 месяца. Чтобы получить 25 тактов, попробуйте MonthLocator.   -  person Quang Hoang    schedule 22.02.2021
comment
ты прав. @QuangHoang, однако, когда я использую ax.xaxis.set_major_locator(mdates.MonthLocator()), я получаю 575 тиков как xticks.   -  person oakca    schedule 22.02.2021
comment
Этот вопрос похож на этот: pandas .plot() частота тиков по оси x — как я могу показать больше тиков?   -  person Patrick FitzGerald    schedule 23.02.2021


Ответы (1)


Matplotlib автоматически выбирает подходящее количество тиков и меток тиков, чтобы ось X не стала нечитаемой. Вы можете переопределить поведение по умолчанию, используя локаторы делений и средства форматирования из matplotlib.dates модуль.

Но обратите внимание, что вы строите временные ряды с помощью pandas plot, который является оболочкой plt.plot. Pandas использует настраиваемые средства форматирования тиков для графики временных рядов, которые создают красиво отформатированные метки в виде делений. Таким образом, он использует единицы измерения по оси X для дат, которые отличаются от единицы даты в matplotlib, что объясняет, почему вы получаете то, что выглядит как случайное количество тиков, когда пытаетесь использовать MonthLocator.

Чтобы сделать график pandas совместимым с matplotlib.dates локаторами отметок, вам нужно добавить недокументировано x_compat=True. К сожалению, это также удаляет форматировщики пользовательских меток pandas. Итак, вот пример того, как использовать локатор тиков даты matplotlib с графиком pandas и получить аналогичный формат тиков (второстепенные тики не включены):

import pandas as pd                # v 1.1.3
import matplotlib.pyplot as plt    # v 3.3.2
import matplotlib.dates as mdates

# Create sample time series stored in a dataframe
ts = pd.DataFrame(data=dict(constant=1),
                  index=pd.date_range('2019-01-01', '2020-12-31', freq='H'))

# Create pandas plot
ax = ts.plot(figsize=(10,4), x_compat=True)
ax.set_xlim(min(ts.index), max(ts.index))

# Select and format x ticks
ax.xaxis.set_major_locator(mdates.MonthLocator())
ticks = pd.to_datetime(ax.get_xticks(), unit='d') # timestamps of x ticks
labels = [timestamp.strftime('%b\n%Y') if timestamp.year != ticks[idx-1].year
          else timestamp.strftime('%b') for idx, timestamp in enumerate(ticks)]
plt.xticks(ticks, labels, rotation=0, ha='center');

пандас_тайм_серия

person Patrick FitzGerald    schedule 23.02.2021