Отметки оси X не отображаются на графике - PullRequest
1 голос
/ 26 октября 2019

Я пытаюсь, чтобы месяцы и годы отображались в формате «Пн ГГГГ» на оси X, но пока я могу отображать только годы.

Я пытался использовать варианты

ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_minor_locator(mdates.MonthLocator())

ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
ax.xaxis.set_minor_formatter(mdates.DateFormatter('%b'))

без успеха.

Вот как выглядит df['login_month'] (то, что я пытаюсь отобразить как ось X):

index   login_month
0       2016-01-01 00:00:00
1       2016-02-01 00:00:00
2       2016-03-01 00:00:00
3       2016-04-01 00:00:00
4       2016-05-01 00:00:00
5       2016-06-01 00:00:00
6       2016-07-01 00:00:00
7       2016-08-01 00:00:00
8       2016-09-01 00:00:00
9       2016-10-01 00:00:00
10      2016-11-01 00:00:00
11      2016-12-01 00:00:00
12      2017-01-01 00:00:00
13      2017-02-01 00:00:00
14      2017-03-01 00:00:00
15      2017-04-01 00:00:00
16      2017-05-01 00:00:00
17      2017-06-01 00:00:00
18      2017-07-01 00:00:00
19      2017-08-01 00:00:00
20      2017-09-01 00:00:00
21      2017-10-01 00:00:00
22      2017-11-01 00:00:00
23      2017-12-01 00:00:00
24      2018-01-01 00:00:00
25      2018-02-01 00:00:00
26      2018-03-01 00:00:00

Код, который я сейчас имею, выглядит следующим образом:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime

df['login_month'] = pd.to_datetime(df['login_month'])

ax = (df.pivot(index='login_month',
          columns='user_month_created',
          values='cumulative_logins')
   .plot.area(figsize=(20,18))
)

#labels
plt.title('cumulative monthly logins by user creation cohort month')
plt.xlabel('login month')
plt.ylabel('cumulative monthly logins (in tens of millions)')

# # ticks
# ax.xaxis.set_major_locator(mdates.YearLocator())
# ax.xaxis.set_minor_locator(mdates.MonthLocator())

# ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
# ax.xaxis.set_minor_formatter(mdates.DateFormatter('%b'))

# # round to nearest years.
# datemin = np.datetime64(df['login_month'][0], 'M')
# datemax = np.datetime64(df['login_month'][1294], 'M') + np.timedelta64(1, 'Y')
# area_plot.set_xlim(xmin=datemin, xmax=datemax)

plt.yticks(np.arange(0, 12000000, 250000))
plt.grid(True)

и в настоящее время он отображает: enter image description here

и в тиковых отметках отсутствуют месяцы и годы

@ baccandr Когда я пытался воспроизвести ваш результат, я получаю следующую ошибку:

AttributeError module 'matplotlib.dates' has no attribute 'ConciseDateFormatter' ---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-66-49dd880fcf13> in <module>
     14 
     15 locator = mdates.AutoDateLocator(minticks=15, maxticks=30)
---> 16 formatter = mdates.ConciseDateFormatter(locator)
     17 axs.xaxis.set_major_locator(locator)
     18 axs.xaxis.set_major_formatter(formatter)

AttributeError: module 'matplotlib.dates' has no attribute 'ConciseDateFormatter'

enter image description here

и следующий график enter image description here

1 Ответ

1 голос
/ 26 октября 2019

Редактировать: , если вы все еще используете matplotlib 2.2.x , вы можете использовать тикер matplotlib api:

import matplotlib.ticker as ticker
#generate some random data
idx= pd.date_range(start='2016-01-01', end='2020-02-01',freq='m')
df=pd.DataFrame({'rand1':np.random.random(len(idx)),
                 'rand2': np.random.random(len(idx)),
                 'rand3': np.random.random(len(idx))},index=idx)
#stack plot
fig, axs = plt.subplots(figsize=(20,18),constrained_layout=True)
axs.stackplot(df.index,df.rand1,df.rand2,df.rand3)

#Adjust ticks
axs.set_xticks(pd.to_datetime(idx.year.unique().astype(str)), minor=False)
axs.xaxis.set_major_formatter(ticker.FixedFormatter(idx.year.unique().astype(str)))

#create bimonthly minor ticks
months=pd.date_range(start=idx[0], end=idx[-1],freq='2M')
axs.set_xticks(pd.to_datetime(months), minor=True)
axs.xaxis.set_minor_formatter(ticker.FixedFormatter(months.month.astype(str)))

#adjust major ticks aesthetics
axs.tick_params(axis='x',which='major',length=5,width=1.5, pad=4, labelsize=14)

ЕслиВы хотите отображать меньше / больше месяцев, вы можете просто настроить частоту в pd.date_range(start=idx[0], end=idx[-1],freq='2M').

Это результат: enter image description here

Для matplotlib3.1.x:

Возможно, я бы использовал matplotlib автоматический указатель даты вместе с кратким форматером даты :

#generate some random data
idx= pd.date_range(start='2016-01-01', end='2020-01-01',freq='m')
df=pd.DataFrame({'rand1':np.random.random(len(idx)),
                 'rand2': np.random.random(len(idx)),
                 'rand3': np.random.random(len(idx))},index=idx)
#stack plot
fig, axs = plt.subplots(figsize=(20,18),constrained_layout=True)
axs.stackplot(df.index,df.rand1,df.rand2,df.rand3)

locator = mdates.AutoDateLocator(minticks=15, maxticks=20)
formatter = mdates.ConciseDateFormatter(locator)
axs.xaxis.set_major_locator(locator)
axs.xaxis.set_major_formatter(formatter)

Изменяя аргумент автодателокатора, вы можете настроить частоту ваших тиков. Здесь вы также можете найти несколько примеров того, как изменить вывод краткого форматера даты.

ps Я использовал функцию стека графиков matplotlib, но вы должны быть в состоянии получитьаналогичный результат также с использованием функции pandas plot.area.

pps на вашем примере я не смог воспроизвести вашу проблему, поскольку диапазон дат слишком короткий, а автоматический форматер из pandas просто работалхорошо.

это результат, который я получил: enter image description here

...