KeyError when plotting a sliced pandas dataframe with dates

In [1]:
%pylab
import numpy as np
from pandas import DataFrame
import datetime

Welcome to pylab, a matplotlib-based Python environment [backend: Qt4Agg].
For more information, type 'help(pylab)'.

A test dataframe

In [2]:
test = DataFrame({'x' : [datetime.datetime(2012,9,10) + datetime.timedelta(n) for n in range(10)], 'y' : range(10)})
test
Out[2]:
x y
0 2012-09-10 00:00:00 0
1 2012-09-11 00:00:00 1
2 2012-09-12 00:00:00 2
3 2012-09-13 00:00:00 3
4 2012-09-14 00:00:00 4
5 2012-09-15 00:00:00 5
6 2012-09-16 00:00:00 6
7 2012-09-17 00:00:00 7
8 2012-09-18 00:00:00 8
9 2012-09-19 00:00:00 9

Trying to plot sliced dataframe with dates

When I try to plot a subset of the dataframe, I get a KeyError when the index does not start with 0, but only with the datetime column:

No problem:

In [3]:
plot(test['x'], test['y'])
Out[3]:
[<matplotlib.lines.Line2D at 0x5cf5e10>]
In [4]:
plot(test['x'])
Out[4]:
[<matplotlib.lines.Line2D at 0x5cfad90>]
In [5]:
plot(test['x'][0:5])
Out[5]:
[<matplotlib.lines.Line2D at 0x5f5b9d0>]
In [6]:
plot(test['y'][5:10])
Out[6]:
[<matplotlib.lines.Line2D at 0x5f5bcd0>]

Problem:

In [7]:
plot(test['x'][5:10])
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-7-aa076e3fc4e0> in <module>()
----> 1 plot(test['x'][5:10])

C:\Python27\lib\site-packages\matplotlib\pyplot.pyc in plot(*args, **kwargs)
   2456         ax.hold(hold)
   2457     try:
-> 2458         ret = ax.plot(*args, **kwargs)
   2459         draw_if_interactive()
   2460     finally:

C:\Python27\lib\site-packages\matplotlib\axes.pyc in plot(self, *args, **kwargs)
   3846         lines = []
   3847 
-> 3848         for line in self._get_lines(*args, **kwargs):
   3849             self.add_line(line)
   3850             lines.append(line)

C:\Python27\lib\site-packages\matplotlib\axes.pyc in _grab_next_args(self, *args, **kwargs)
    321                 return
    322             if len(remaining) <= 3:
--> 323                 for seg in self._plot_args(remaining, kwargs):
    324                     yield seg
    325                 return

C:\Python27\lib\site-packages\matplotlib\axes.pyc in _plot_args(self, tup, kwargs)
    298             x = np.arange(y.shape[0], dtype=float)
    299 
--> 300         x, y = self._xy_from_xy(x, y)
    301 
    302         if self.command == 'plot':

C:\Python27\lib\site-packages\matplotlib\axes.pyc in _xy_from_xy(self, x, y)
    215         if self.axes.xaxis is not None and self.axes.yaxis is not None:
    216             bx = self.axes.xaxis.update_units(x)
--> 217             by = self.axes.yaxis.update_units(y)
    218 
    219             if self.command!='plot':

C:\Python27\lib\site-packages\matplotlib\axis.pyc in update_units(self, data)
   1277         neednew = self.converter!=converter
   1278         self.converter = converter
-> 1279         default = self.converter.default_units(data, self)
   1280         #print 'update units: default=%s, units=%s'%(default, self.units)
   1281         if default is not None and self.units is None:

C:\Python27\lib\site-packages\matplotlib\dates.pyc in default_units(x, axis)
   1153         'Return the tzinfo instance of *x* or of its first element, or None'
   1154         try:
-> 1155             x = x[0]
   1156         except (TypeError, IndexError):
   1157             pass

C:\Python27\lib\site-packages\pandas\core\series.pyc in __getitem__(self, key)
    374     def __getitem__(self, key):
    375         try:
--> 376             return self.index.get_value(self, key)
    377         except InvalidIndexError:
    378             pass

C:\Python27\lib\site-packages\pandas\core\index.pyc in get_value(self, series, key)
    529         """
    530         try:
--> 531             return self._engine.get_value(series, key)
    532         except KeyError, e1:
    533             if len(self) > 0 and self.inferred_type == 'integer':

C:\Python27\lib\site-packages\pandas\_engines.pyd in pandas._engines.IndexEngine.get_value (pandas\src\engines.c:1479)()

C:\Python27\lib\site-packages\pandas\_engines.pyd in pandas._engines.IndexEngine.get_value (pandas\src\engines.c:1374)()

C:\Python27\lib\site-packages\pandas\_engines.pyd in pandas._engines.DictIndexEngine.get_loc (pandas\src\engines.c:2498)()

C:\Python27\lib\site-packages\pandas\_engines.pyd in pandas._engines.DictIndexEngine.get_loc (pandas\src\engines.c:2460)()

KeyError: 0
In [19]:
plot(test['y'][0:5])
Out[19]:
[<matplotlib.lines.Line2D at 0x8a6b130>]
In [20]:
plot(test['y'][5:10])
Out[20]:
[<matplotlib.lines.Line2D at 0x8e0cdf0>]

Possible solutions

First call np.asarray before plotting

In [18]:
plot(np.asarray(test['x'][5:10]))
Out[18]:
[<matplotlib.lines.Line2D at 0x8d88bb0>]

Use the pandas plot method

In [10]:
test['x'][5:10].plot()
Out[10]:
<matplotlib.axes.AxesSubplot at 0x61a6eb0>
In [15]:
test.plot(x='x', y='y') # only from pandas 0.8
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-97a51447d017> in <module>()
----> 1 test.plot(x='x', y='y')

C:\Python27\lib\site-packages\pandas\tools\plotting.pyc in plot_frame(frame, subplots, sharex, sharey, use_index, figsize, grid, legend, rot, ax, title, xlim, ylim, logy, xticks, yticks, kind, sort_columns, fontsize, **kwds)
    530                      title=title, grid=grid, figsize=figsize, logy=logy,
    531                      sort_columns=sort_columns, **kwds)
--> 532     plot_obj.generate()
    533     plot_obj.draw()
    534     if subplots:

C:\Python27\lib\site-packages\pandas\tools\plotting.pyc in generate(self)
    196         self._compute_plot_data()
    197         self._setup_subplots()
--> 198         self._make_plot()
    199         self._post_plot_logic()
    200         self._adorn_subplots()

C:\Python27\lib\site-packages\pandas\tools\plotting.pyc in _make_plot(self)
    338                 style = self.style
    339 
--> 340             plotf(ax, x, y, style, label=label, **self.kwds)
    341             ax.grid(self.grid)
    342 

C:\Python27\lib\site-packages\matplotlib\axes.pyc in plot(self, *args, **kwargs)
   3846         lines = []
   3847 
-> 3848         for line in self._get_lines(*args, **kwargs):
   3849             self.add_line(line)
   3850             lines.append(line)

C:\Python27\lib\site-packages\matplotlib\axes.pyc in _grab_next_args(self, *args, **kwargs)
    321                 return
    322             if len(remaining) <= 3:
--> 323                 for seg in self._plot_args(remaining, kwargs):
    324                     yield seg
    325                 return

C:\Python27\lib\site-packages\matplotlib\axes.pyc in _plot_args(self, tup, kwargs)
    308         ncx, ncy = x.shape[1], y.shape[1]
    309         for j in xrange(max(ncx, ncy)):
--> 310             seg = func(x[:,j%ncx], y[:,j%ncy], kw, kwargs)
    311             ret.append(seg)
    312         return ret

C:\Python27\lib\site-packages\matplotlib\axes.pyc in _makeline(self, x, y, kw, kwargs)
    258                      **kw
    259                      )
--> 260         self.set_lineprops(seg, **kwargs)
    261         return seg
    262 

C:\Python27\lib\site-packages\matplotlib\axes.pyc in set_lineprops(self, line, **kwargs)
    199             funcName = "set_%s"%key
    200             if not hasattr(line,funcName):
--> 201                 raise TypeError, 'There is no line property "%s"'%key
    202             func = getattr(line,funcName)
    203             func(val)

TypeError: There is no line property "y"
Back to top