bar plot with datetime x axis

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

bar plot with datetime x axis

SteveAplin
Hello everyone,

Having a bit of an adventure controlling the display of the x axis when plotting a pandas dataframe or series using pandas plot(), as in df.plot(kind='bar') or s.plot(kind='bar').

Here's the head of one column:
1996-01-01    180.0
1997-01-01    159.0
1998-01-01    159.0
1999-01-01    152.0
2000-01-01    121.0
Name: column A, dtype: float64

... and here's its index:
DatetimeIndex(['1996-01-01', '1997-01-01', '1998-01-01', '1999-01-01',
               '2000-01-01', ... ],
              dtype='datetime64[ns]', freq=None)
I want to show a bunch of subplots, so my code looks like this:
from datetime import datetime
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib.dates as mdates
%matplotlib inline

fig, axs = plt.subplots(9,2,figsize=(20,20),sharex=True)
for i,col in enumerate(df):
    ax = df[col].plot(kind='bar',ax=axs[i,0])
   etc.

... which gives an x tick value for each index item (i.e. each bar), in full datetime format (YYYY-MM-DD 00:00:00), rotated 90 degrees.

I don't want full datetime format, I just want the year portion. Googling the issue led me to trying this:

fig.autofmt_xdate()

... which rotates the labels, but still in full datetime format.

So I tried adding
formatter = mdates.DateFormatter('%Y')
ax.xaxis.set_major_formatter(formatter)

which throws this error:
ValueError: DateFormatter found a value of x=0, which is an illegal date.  This usually occurs because you have not informed the axis that it is plotting dates, e.g., with ax.xaxis_date()
... which is a bit confusing, since the index is a pandas datetimeindex.

Any ideas about how I could get my xaxis to not show just the year portion?

Thanks in advance!

Stephen E. Aplin
Ottawa Canada

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: bar plot with datetime x axis

Christopher Short
Hi Steve,

When it comes to bar plots, Pandas doesn’t pass a datetime object to matplotlib  (it’s an old issue).

That’s the reason for the error when attempting to format a date  - it isn’t one.

Easiest solution is to plot directly with matplotlib

In your notation below that would be: (nothing - you don’t need to pass the returned axes back to anything)

fmt = mdates.DateFormatter('%Y’)

for i,col in enumerate(df):

axs[i,0].bar(df.index,  df[col])

axs[i,0].xaxis.set_major_formatter(fmt)


Though it might be easier to read to omit I, and  zip the two elements together and loop over them like this::

fig, axs = plt.subplots(9,2,figsize=(20,20),sharex=True)

for col, ax in zip(df.columns, axs.flatten()):
ax.bar(df.index,df[col])
ax.xaxis.set_major_formatter(fmt)


That will give you horizontal, rather than vertical text as well.

If you need to rotate to fit all the years in use,

ax.tick_params(labelrotation=30, axis=‘x)   #or whatever angle you want

 Or use a locator to specific what you want

cheers
Chris


On 9 May 2018, at 11:06 pm, Steve Aplin <[hidden email]> wrote:

Hello everyone,

Having a bit of an adventure controlling the display of the x axis when plotting a pandas dataframe or series using pandas plot(), as in df.plot(kind='bar') or s.plot(kind='bar').

Here's the head of one column:
1996-01-01    180.0
1997-01-01    159.0
1998-01-01    159.0
1999-01-01    152.0
2000-01-01    121.0
Name: column A, dtype: float64

... and here's its index:
DatetimeIndex(['1996-01-01', '1997-01-01', '1998-01-01', '1999-01-01',
               '2000-01-01', ... ],
              dtype='datetime64[ns]', freq=None)
I want to show a bunch of subplots, so my code looks like this:
from datetime import datetime
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import matplotlib.dates as mdates
%matplotlib inline

fig, axs = plt.subplots(9,2,figsize=(20,20),sharex=True)
for i,col in enumerate(df):
    ax = df[col].plot(kind='bar',ax=axs[i,0])
   etc.

... which gives an x tick value for each index item (i.e. each bar), in full datetime format (YYYY-MM-DD 00:00:00), rotated 90 degrees.

I don't want full datetime format, I just want the year portion. Googling the issue led me to trying this:

fig.autofmt_xdate()

... which rotates the labels, but still in full datetime format.

So I tried adding
formatter = mdates.DateFormatter('%Y')
ax.xaxis.set_major_formatter(formatter)

which throws this error:
ValueError: DateFormatter found a value of x=0, which is an illegal date.  This usually occurs because you have not informed the axis that it is plotting dates, e.g., with ax.xaxis_date()
... which is a bit confusing, since the index is a pandas datetimeindex.

Any ideas about how I could get my xaxis to not show just the year portion?

Thanks in advance!

Stephen E. Aplin
Ottawa Canada
_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users