'Set xlim for pandas/matplotlib where index is string
I have a pandas dataframe that uses strings as index. How can I set xlim for the x axis when my dataframe index is of type object? I tried adding two additional years one at the end and one at the beginning where all datasets are np.nan but that didn't work.
Here is the dataframe

The datatype of index is object
df.index
Out[52]: Index(['2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010', '2011', '2012'], dtype='object')
Here is the plot

So I would like to have some extra space on the x-axis in so the values for the fist and last year are better visible. What could I do?
EDIT:
Here is a minimal example using objects and not date objects as index
Solution 1:[1]
from __future__ import print_function
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
df = pd.DataFrame({'Foo': pd.Series([2,3,4], index=['2002', '2003', '2004'])})
fig, ax = plt.subplots()
df.plot(ax=ax)
which gets you the plot. To take a look at how the x-ticks are getting dealt with look at:
# note this is an AutoLocator
print(ax.xaxis.get_major_locator())
# note this is a FixedFormatter
print(ax.xaxis.get_major_formatter())
# these are the ticks that are used
ff = ax.xaxis.get_major_formatter()
print(ff.seq)
This means that if you pan around the tick labels will stay the same, but will be at random positions. This is the same problem as changing the xlim, the way pandas sets up the plot initially the tick labels are completely decoupled from the data.
One (verbose) way to fix this is:
ax.xaxis.set_major_locator(mticker.FixedLocator(np.arange(len(df))))
ax.xaxis.set_major_formatter(mticker.FixedFormatter(df.index))
# note this is a FixedLocator
print(ax.xaxis.get_major_locator())
# note this is a FixedFormatter
print(ax.xaxis.get_major_formatter())
This will work no matter what you set your index to (strings vs dates)
I have created an issue with pandas https://github.com/pydata/pandas/issues/7612
Solution 2:[2]
Use set_xlim, +1 means moving 1 unit to the right and -1 means the reverse. In the following example I expanded the plot 0.5 months each side:
df=pd.DataFrame({'A': range(10), 'B': range(1, 11), 'C': range(2,12)})
df.index=pd.date_range('2001/01/01', periods=10, freq='M')
ax=df.plot(kind='line')
ax.set_xlim(np.array([-0.5, 0.5])+ax.get_xlim())

Edit, to have xticklabel for every year, instead the default every two years in pandas:
ax=df.plot(kind='line', xticks=df.index)
ax.set_xticklabels(df.index.map(lambda x: datetime.datetime.strftime(x, '%Y')))

Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
