简体   繁体   中英

x-axis tick marks not appearing in graph

I'm trying to get months and years to show up in a 'Mon YYYY' format on the x-axis, but so far I'm only able to get the years to show up.

I've tried using variations of

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'))

without success.

Here is what df['login_month'] (what I'm trying to display as the x-axis) looks like:

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

The code I have right now is as follows:

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)

and it currently plots: 在此处输入图像描述

and it's missing the months and years in the tick marks

@baccandr When I tried to reproduce your result, I get the following error:

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'

在此处输入图像描述

and the following graph在此处输入图像描述

Edit: if you are still running on matplotlib 2.2.x you could use matplotlib ticker 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)

If you want to display less/more months you can simply adjust the frequency in pd.date_range(start=idx[0], end=idx[-1],freq='2M') .

This is the result: 在此处输入图像描述

For matplotlib 3.1.x:

I would probably use the matplotlib auto date locator together with the concise date formatter :

#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)

By changing the argument of the autodatelocator you can adjust the frequency of your ticks. Here you can also find some examples on how to change the output of the concise date formatter.

ps I used matplotlib stackplot function but you should be able to obtain a similar result also using pandas plot.area function.

pps with your example I was not able to reproduce your issue because the date span is too short and the automatic formatter from pandas just worked fine.

this is the result I got: 在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM