форматирование временных рядов по оси абсцисс в пандах / матплотлиб

1

Я хотел бы показать каждую аббревиатуру месяца, а также год в году.

Я довольно близко. Проблема, с которой я в настоящее время сталкиваюсь, заключается в том, что эти годы неверны. Я понял, что это проблема между numpy.datetime64 (индекс datetime в этом формате) и datetime python, который используется в эпоху 1970 года. Два года, показанные на графике, должны быть в 2017 и 2018 годах, но они показывают 48 и 49.

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

from matplotlib.dates import MonthLocator, WeekdayLocator, DateFormatter, YearLocator

indx = pd.date_range('2017-04-01', '2019-01-01')
s = pd.Series(np.random.randn(len(indx)), index=indx)

df = pd.DataFrame(s)

ax = df.plot()
months = MonthLocator(range(1, 13), bymonthday=1, interval=1)
monthsFmt = DateFormatter("%b")
years = YearLocator(1, month=4, day=1)
yrsFmt = DateFormatter("\n %y")

ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(yrsFmt)


ax.xaxis.set_minor_locator(months)
ax.xaxis.set_minor_formatter(monthsFmt)

plt.show()

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

Изображение 174551

Теги:
matplotlib
numpy
datetime

2 ответа

1

Matplotlib отсчитывает годы от нуля, но UNIX с 1970 года. Поэтому вы получили годы 48, 49 и т.д. Чтобы избежать такого поведения matplotlib, вам нужно получить от вашей части даты индекса времени pandas datetime, а затем использовать дескриптор %Y получить полные годы для крупных клещей:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import MonthLocator, WeekdayLocator, DateFormatter, YearLocator

indx = pd.date_range('2017-04-01', '2019-01-01')
s = pd.Series(np.random.randn(len(indx)), index=indx.date) # get dates
df = pd.DataFrame(s)

months = MonthLocator() # MonthLocator without args set ticks for every month
monthsFmt = DateFormatter("%b")
years = YearLocator(month=4, day=1)
yrsFmt = DateFormatter("\n%Y") # correct year descriptor

ax = df.plot()
ax.xaxis.set_minor_locator(months)
ax.xaxis.set_minor_formatter(monthsFmt)
for tick in ax.xaxis.get_minor_ticks():tick.label.set_fontsize(9) 
ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(yrsFmt)

plt.show()

Изображение 174551

1

После некоторого воспроизведения вокруг, похоже, будет работать, если вы укажете ось и затем нарисуете ее (вместо вызова функции графика pandas).

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

from matplotlib.dates import MonthLocator, WeekdayLocator, DateFormatter, YearLocator

indx = pd.date_range('2017-04-01', '2019-01-01')
s = pd.Series(np.random.randn(len(indx)), index=indx)

df = pd.DataFrame(s)

fig, ax = plt.subplots(1)
ax.plot(df)

months = MonthLocator(range(1, 13), bymonthday=1, interval=1)
monthsFmt = DateFormatter("%b")
years = YearLocator(1, month=4, day=1)
yrsFmt = DateFormatter("\n %Y")

ax.xaxis.set_major_locator(years)
ax.xaxis.set_major_formatter(yrsFmt)


ax.xaxis.set_minor_locator(months)
ax.xaxis.set_minor_formatter(monthsFmt)

fig.show()

Также обратите внимание, что я изменил % y на % Y, поэтому он отформатирован как 2017/2018, а не 17/18. Изображение 174551

  • 0
    Благодарю. Это сработало для дат, но заставило мою легенду исчезнуть с ошибкой: UserWarning: Помеченные объекты не найдены. Используйте label = '...' kwarg на отдельных участках. есть идеи? У меня есть вызов ax.legend (), который работает в исходном коде.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню