From 4cc8ea223eec29e54e9f0dc0a876e16e59d4f4d5 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Sat, 28 Oct 2017 14:21:56 -0700 Subject: [PATCH] Fix errors that appear after update to pandas 0.21 Fixes GH1661 (datetime coordinates in matplotlib) Also fixes a test suite failure in test_indexing.py due to a changed pandas exception type. --- doc/whats-new.rst | 4 ++++ xarray/plot/facetgrid.py | 7 ++++--- xarray/plot/plot.py | 7 ++++--- xarray/plot/utils.py | 19 +++++++++++++++++++ xarray/tests/test_indexing.py | 6 ++++-- 5 files changed, 35 insertions(+), 8 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index cbc4ea35e94..d8ae75253d6 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -346,6 +346,10 @@ Bug fixes - Fix ``rasterio`` backend for Rasterio versions 1.0alpha10 and newer. (:issue:`1641`). By `Chris Holden `_. +- Fix plotting with datetime64 axis labels under pandas 0.21 and newer + (:issue:`1661`). + By `Stephan Hoyer `_. + .. _whats-new.0.9.6: v0.9.6 (8 June 2017) diff --git a/xarray/plot/facetgrid.py b/xarray/plot/facetgrid.py index b2253b926b8..98841b6a939 100644 --- a/xarray/plot/facetgrid.py +++ b/xarray/plot/facetgrid.py @@ -10,7 +10,8 @@ import numpy as np from ..core.formatting import format_item -from .utils import _determine_cmap_params, _infer_xy_labels +from .utils import (_determine_cmap_params, _infer_xy_labels, + import_matplotlib_pyplot) # Overrides axes.labelsize, xtick.major.size, ytick.major.size @@ -101,7 +102,7 @@ def __init__(self, data, col=None, row=None, col_wrap=None, """ - import matplotlib.pyplot as plt + plt = import_matplotlib_pyplot() # Handle corner case of nonunique coordinates rep_col = col is not None and not data[col].to_index().is_unique @@ -409,7 +410,7 @@ def map(self, func, *args, **kwargs): self : FacetGrid object """ - import matplotlib.pyplot as plt + plt = import_matplotlib_pyplot() for ax, namedict in zip(self.axes.flat, self.name_dicts.flat): if namedict is not None: diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py index 15b713e4140..0320b49b5be 100644 --- a/xarray/plot/plot.py +++ b/xarray/plot/plot.py @@ -15,7 +15,8 @@ import pandas as pd from datetime import datetime -from .utils import _determine_cmap_params, _infer_xy_labels, get_axis +from .utils import (_determine_cmap_params, _infer_xy_labels, get_axis, + import_matplotlib_pyplot) from .facetgrid import FacetGrid from xarray.core.pycompat import basestring @@ -179,7 +180,7 @@ def line(darray, *args, **kwargs): Additional arguments to matplotlib.pyplot.plot """ - import matplotlib.pyplot as plt + plt = import_matplotlib_pyplot() ndims = len(darray.dims) if ndims != 1: @@ -429,7 +430,7 @@ def newplotfunc(darray, x=None, y=None, figsize=None, size=None, return _easy_facetgrid(**allargs) - import matplotlib.pyplot as plt + plt = import_matplotlib_pyplot() # colors is mutually exclusive with cmap if cmap and colors: diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py index 83ff2c6ca00..169aa121e9e 100644 --- a/xarray/plot/utils.py +++ b/xarray/plot/utils.py @@ -40,6 +40,25 @@ def import_seaborn(): return sns +_registered = False + + +def register_pandas_datetime_converter_if_needed(): + # based on https://github.com/pandas-dev/pandas/pull/17710 + global _registered + if not _registered: + from pandas.tseries import converter + converter.register() + _registered = True + + +def import_matplotlib_pyplot(): + """Import pyplot as register appropriate converters.""" + register_pandas_datetime_converter_if_needed() + import matplotlib.pyplot as plt + return plt + + def _determine_extend(calc_data, vmin, vmax): extend_min = calc_data.min() < vmin extend_max = calc_data.max() > vmax diff --git a/xarray/tests/test_indexing.py b/xarray/tests/test_indexing.py index f8268ea2d6d..1667232e9be 100644 --- a/xarray/tests/test_indexing.py +++ b/xarray/tests/test_indexing.py @@ -61,8 +61,10 @@ def test_convert_label_indexer(self): indexing.convert_label_indexer(mindex, 0) with self.assertRaises(ValueError): indexing.convert_label_indexer(index, {'three': 0}) - with self.assertRaisesRegexp(KeyError, 'index to be fully lexsorted'): - indexing.convert_label_indexer(mindex, (slice(None), 1, 'no_level')) + with self.assertRaises((KeyError, IndexError)): + # pandas 0.21 changed this from KeyError to IndexError + indexing.convert_label_indexer( + mindex, (slice(None), 1, 'no_level')) def test_convert_unsorted_datetime_index_raises(self): index = pd.to_datetime(['2001', '2000', '2002'])