Importing pandas in python changes how matplotlib handles datetime objects?

On my debian compression system, I ran into a python problem that could be redone like this:

import numpy import datetime from matplotlib import pyplot x = [datetime.datetime.utcfromtimestamp(i) for i in numpy.arange(100000,200000,3600)] y = range(len(x)) # See matplotlib handle a series of datetimes just fine.. pyplot.plot(x, y) # [<matplotlib.lines.Line2D object at 0xad10f4c>] import pandas # Now we try exactly what we did before.. pyplot.plot(x, y) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/pymodules/python2.6/matplotlib/pyplot.py", line 2141, in plot ret = ax.plot(*args, **kwargs) File "/usr/lib/pymodules/python2.6/matplotlib/axes.py", line 3432, in plot for line in self._get_lines(*args, **kwargs): File "/usr/lib/pymodules/python2.6/matplotlib/axes.py", line 311, in _grab_next_args for seg in self._plot_args(remaining, kwargs): File "/usr/lib/pymodules/python2.6/matplotlib/axes.py", line 288, in _plot_args x, y = self._xy_from_xy(x, y) File "/usr/lib/pymodules/python2.6/matplotlib/axes.py", line 204, in _xy_from_xy bx = self.axes.xaxis.update_units(x) File "/usr/lib/pymodules/python2.6/matplotlib/axis.py", line 982, in update_units self._update_axisinfo() File "/usr/lib/pymodules/python2.6/matplotlib/axis.py", line 994, in _update_axisinfo info = self.converter.axisinfo(self.units, self) File "/usr/local/lib/python2.6/dist-packages/pandas/tseries/converter.py", line 184, in axisinfo majfmt = PandasAutoDateFormatter(majloc, tz=tz) File "/usr/local/lib/python2.6/dist-packages/pandas/tseries/converter.py", line 195, in __init__ dates.AutoDateFormatter.__init__(self, locator, tz, defaultfmt) TypeError: __init__() takes at most 3 arguments (4 given) 

I'm not interested in the reason for the specific error shown, it is obvious that pandas expects a different version of matplotlib - that there is a fair risk of getting one package from the standard debian repository, and the other via pip, and I already "solved" this part of the problem by allowing pip to update matplotlib.

The real problem - and now the triple question arises: how can it be that only pandas import violated the ability of matplotlib to process datetime objects when only two lines before pandas did not explicitly participate in the same operation? Does pandas affect when importing without modification other modules in the top-level namespace to force them to use pandas methods? And is this acceptable behavior for a python module? Since I need to rely on this that importing, say, a module with an arbitrary number, will not change, say, the brine module, in order to apply a random salt to everything that it writes.

Update with additional information

python - 2.6.6 (current stable debian from package 2.6.6-3 + squeeze7)

matplotlib version was debian 0.99.3-1 (current stable debian from python-matplotlib package)

pandas version was 0.9.0 (installed with 'pip install pandas', some time ago - not today)

I386 platform powered by debian Squeeze

Replication steps

  • (obviously) Bootstrap pure debian compresses the installation of i386 and chroot into it.
  • apt-get update
  • apt-get install python python-matplotlib
  • apt-get install python-pip build-essential python-dev
  • pip install --upgrade numpy
  • pip install pandas

Now start an interactive python session

 import numpy import datetime # Next two lines added to original example to avoid hassle with DISPLAY in chroot import matplotlib matplotlib.use('agg') from matplotlib import pyplot x = [datetime.datetime.utcfromtimestamp(i) for i in numpy.arange(100000,200000,3600)] y = range(len(x)) pyplot.plot(x, y) import pandas pyplot.plot(x, y) 
+4
source share
1 answer

When importing pandas it registers a bunch of unit converters with matplotlib . This is from more updated versions of both libraries, but I assume that the general behavior is the same.

 In [4]: import matplotlib.units as muints In [5]: muints.registry Out[5]: {datetime.date: <matplotlib.dates.DateConverter instance at 0x2ab8908>, datetime.datetime: <matplotlib.dates.DateConverter instance at 0x2ab8ab8>} In [6]: import pandas In [7]: muints.registry Out[7]: {pandas.tseries.period.Period: <pandas.tseries.converter.PeriodConverter instance at 0x2627e60>, pandas.tslib.Timestamp: <pandas.tseries.converter.DatetimeConverter instance at 0x264ea28>, datetime.date: <pandas.tseries.converter.DatetimeConverter instance at 0x2532fc8>, datetime.datetime: <pandas.tseries.converter.DatetimeConverter instance at 0x2627ab8>, datetime.time: <pandas.tseries.converter.TimeConverter instance at 0x2532f38>} 

This registry is used by axis (with several levels of redirection) to determine how to format information that is not a number, and it corresponds to the class of the thing it is trying to label (therefore, entries in the dictionary with the key datetime.* ).

I suspect you can fix this by replacing the breaking entries in the dict

+3
source

All Articles