Skip to content

Commit 67aa721

Browse files
author
dcherian
committed
Squashed commit of the following:
commit 37a947a Author: Deepak Cherian <[email protected]> Date: Wed Jan 30 09:20:57 2019 -0800 Refactor plot utils (#2670) * Refactor out utility functions. * facetgrid refactor 1. refactor out _easy_facetgrid 2. Combine map_dataarray_line with map_dataarray * flake8 * Refactor out colorbar making to plot.utils._add_colorbar * Refactor out cmap_params, cbar_kwargs processing * Back to map_dataarray_line * lint * small rename * review comment. * Move _infer_line_data back. commit fd2552a Author: Spencer Clark <[email protected]> Date: Wed Jan 30 11:45:09 2019 -0500 Enable subtracting a scalar cftime.datetime object from a CFTimeIndex (#2672) * Enable subtracting a scalar cftime.datetime object from a CFTimeIndex * lint * Test cftime.datetime minus CFTimeIndex as well * Fix cftime minus CFTimeIndex commit e8bf4bf Author: Tom Nicholas <[email protected]> Date: Wed Jan 30 02:02:22 2019 +0000 Bugfix for line plot axes (#2726) * Fixed logic for setting line data * Added tests to check line data matches values of correct coords * Recorded bugfix for line plots * Update doc/whats-new.rst Co-Authored-By: TomNicholas <[email protected]> * Update doc/whats-new.rst Co-Authored-By: TomNicholas <[email protected]> commit 620b946 Author: Stephan Hoyer <[email protected]> Date: Sun Jan 27 13:02:03 2019 -0800 Fix test failures / warnings for pandas 0.24 (#2720) * Fix test failures / warnings for pandas 0.24 Fixes GH2717 * Brief doc note * Comment on name order commit 882deac Author: Stephan Hoyer <[email protected]> Date: Sun Jan 27 09:11:47 2019 -0800 DOC: refresh whats-new for 0.11.3 / 0.12.0 (#2718) commit 8ca8efe Author: Stephan Hoyer <[email protected]> Date: Sat Jan 26 10:14:49 2019 -0800 Update environment for doc build (#2708) * Update environment for doc build We were pinning very old versions for most of these packages. This should fix the failures on ReadTheDocs. * Build fixes commit 2e99c7d Author: Stephan Hoyer <[email protected]> Date: Fri Jan 25 13:52:17 2019 -0800 Print full environment fron conf.py (#2709) This should make it easier to debug the doc build environment. commit cc5015a Author: Stephan Hoyer <[email protected]> Date: Fri Jan 25 11:55:07 2019 -0800 BUG: ensure indexes are reset when coords are modified (#2707) This was introduced by the recent indexes refactor, but never made it into a release. commit aabda43 Author: Joe Hamman <[email protected]> Date: Fri Jan 25 08:38:45 2019 -0800 Remove py2 compat (#2645) * strip out PY2 compat code from pycompat.py * isort * remove 2 unused imports * remove extra import * no more future * no unicode literals * no more ReprMixin * cleanup merge * remove deprecated imports from collections * 2 more cleanups from shoyer
1 parent 0e4bc7a commit 67aa721

File tree

8 files changed

+143
-3
lines changed

8 files changed

+143
-3
lines changed

doc/whats-new.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ Bug fixes
5858
from higher frequencies to lower frequencies. Datapoints outside the bounds
5959
of the original time coordinate are now filled with NaN (:issue:`2197`). By
6060
`Spencer Clark <https://github.com/spencerkclark>`_.
61+
- Line plots with the `x` argument set to a non-dimensional coord now plot the correct data for 1D DataArrays.
62+
(:issue:`27251). By `Tom Nicholas <http://github.com/TomNicholas>`_.
63+
- Subtracting a scalar ``cftime.datetime`` object from a
64+
:py:class:`CFTimeIndex` now results in a :py:class:`pandas.TimedeltaIndex`
65+
instead of raising a ``TypeError`` (:issue:`2671`). By `Spencer Clark
66+
<https://github.com/spencerkclark>`_.
6167

6268
.. _whats-new.0.11.3:
6369

xarray/coding/cftimeindex.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,17 @@ def __radd__(self, other):
408408
return CFTimeIndex(other + np.array(self))
409409

410410
def __sub__(self, other):
411-
if isinstance(other, CFTimeIndex):
411+
import cftime
412+
if isinstance(other, (CFTimeIndex, cftime.datetime)):
412413
return pd.TimedeltaIndex(np.array(self) - np.array(other))
413414
elif isinstance(other, pd.TimedeltaIndex):
414415
return CFTimeIndex(np.array(self) - other.to_pytimedelta())
415416
else:
416417
return CFTimeIndex(np.array(self) - other)
417418

419+
def __rsub__(self, other):
420+
return pd.TimedeltaIndex(other - np.array(self))
421+
418422
def _add_delta(self, deltas):
419423
# To support TimedeltaIndex + CFTimeIndex with older versions of
420424
# pandas. No longer used as of pandas 0.23.

xarray/core/missing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from .common import _contains_datetime_like_objects
1111
from .computation import apply_ufunc
1212
from .duck_array_ops import dask_array_type
13-
from .utils import OrderedSet, is_scalar
13+
from .utils import OrderedSet, datetime_to_numeric, is_scalar
1414
from .variable import Variable, broadcast_variables
1515

1616

xarray/plot/facetgrid.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from ..core.formatting import format_item
99
from .utils import (
10-
_infer_line_data, _infer_xy_labels, _process_cmap_cbar_kwargs,
10+
_infer_xy_labels, _process_cmap_cbar_kwargs,
1111
import_matplotlib_pyplot, label_from_attrs)
1212

1313
# Overrides axes.labelsize, xtick.major.size, ytick.major.size
@@ -224,6 +224,7 @@ def map_dataarray(self, func, x, y, **kwargs):
224224

225225
cmap_params, cbar_kwargs = _process_cmap_cbar_kwargs(
226226
func, kwargs, self.data.values)
227+
227228
self._cmap_extend = cmap_params.get('extend')
228229

229230
# Order is important
@@ -251,6 +252,7 @@ def map_dataarray(self, func, x, y, **kwargs):
251252
return self
252253

253254
def map_dataarray_line(self, func, x, y, **kwargs):
255+
from .plot import _infer_line_data
254256

255257
add_legend = kwargs.pop('add_legend', True)
256258
kwargs['add_legend'] = False

xarray/plot/plot.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,100 @@
1515

1616
from .facetgrid import _easy_facetgrid
1717
from .utils import (
18+
<<<<<<< HEAD
1819
_add_colorbar, _ensure_plottable, _infer_interval_breaks, _infer_line_data,
1920
_infer_xy_labels, _interval_to_double_bound_points,
2021
_interval_to_mid_points, _process_cmap_cbar_kwargs, _rescale_imshow_rgb,
2122
_resolve_intervals_2dplot, _update_axes, _valid_other_type, get_axis,
2223
import_matplotlib_pyplot, label_from_attrs)
2324

2425

26+
=======
27+
_add_colorbar, _ensure_plottable, _infer_interval_breaks, _infer_xy_labels,
28+
_interval_to_double_bound_points, _interval_to_mid_points,
29+
_process_cmap_cbar_kwargs, _rescale_imshow_rgb, _resolve_intervals_2dplot,
30+
_update_axes, _valid_other_type, get_axis, import_matplotlib_pyplot,
31+
label_from_attrs)
32+
33+
34+
def _infer_line_data(darray, x, y, hue):
35+
error_msg = ('must be either None or one of ({0:s})'
36+
.format(', '.join([repr(dd) for dd in darray.dims])))
37+
ndims = len(darray.dims)
38+
39+
if x is not None and x not in darray.dims and x not in darray.coords:
40+
raise ValueError('x ' + error_msg)
41+
42+
if y is not None and y not in darray.dims and y not in darray.coords:
43+
raise ValueError('y ' + error_msg)
44+
45+
if x is not None and y is not None:
46+
raise ValueError('You cannot specify both x and y kwargs'
47+
'for line plots.')
48+
49+
if ndims == 1:
50+
huename = None
51+
hueplt = None
52+
huelabel = ''
53+
54+
if x is not None:
55+
xplt = darray[x]
56+
yplt = darray
57+
58+
elif y is not None:
59+
xplt = darray
60+
yplt = darray[y]
61+
62+
else: # Both x & y are None
63+
dim = darray.dims[0]
64+
xplt = darray[dim]
65+
yplt = darray
66+
67+
else:
68+
if x is None and y is None and hue is None:
69+
raise ValueError('For 2D inputs, please'
70+
'specify either hue, x or y.')
71+
72+
if y is None:
73+
xname, huename = _infer_xy_labels(darray=darray, x=x, y=hue)
74+
xplt = darray[xname]
75+
if xplt.ndim > 1:
76+
if huename in darray.dims:
77+
otherindex = 1 if darray.dims.index(huename) == 0 else 0
78+
otherdim = darray.dims[otherindex]
79+
yplt = darray.transpose(otherdim, huename)
80+
xplt = xplt.transpose(otherdim, huename)
81+
else:
82+
raise ValueError('For 2D inputs, hue must be a dimension'
83+
+ ' i.e. one of ' + repr(darray.dims))
84+
85+
else:
86+
yplt = darray.transpose(xname, huename)
87+
88+
else:
89+
yname, huename = _infer_xy_labels(darray=darray, x=y, y=hue)
90+
yplt = darray[yname]
91+
if yplt.ndim > 1:
92+
if huename in darray.dims:
93+
otherindex = 1 if darray.dims.index(huename) == 0 else 0
94+
xplt = darray.transpose(otherdim, huename)
95+
else:
96+
raise ValueError('For 2D inputs, hue must be a dimension'
97+
+ ' i.e. one of ' + repr(darray.dims))
98+
99+
else:
100+
xplt = darray.transpose(yname, huename)
101+
102+
huelabel = label_from_attrs(darray[huename])
103+
hueplt = darray[huename]
104+
105+
xlabel = label_from_attrs(xplt)
106+
ylabel = label_from_attrs(yplt)
107+
108+
return xplt, yplt, hueplt, xlabel, ylabel, huelabel
109+
110+
111+
>>>>>>> upstream/master
25112
def plot(darray, row=None, col=None, col_wrap=None, ax=None, hue=None,
26113
rtol=0.01, subplot_kws=None, **kwargs):
27114
"""
@@ -603,6 +690,10 @@ def newplotfunc(darray, x=None, y=None, figsize=None, size=None,
603690
cbar_kwargs['label'] = label_from_attrs(darray)
604691
cbar = _add_colorbar(primitive, ax, cbar_ax, cbar_kwargs,
605692
cmap_params)
693+
<<<<<<< HEAD
694+
=======
695+
696+
>>>>>>> upstream/master
606697
elif (cbar_ax is not None or cbar_kwargs):
607698
# inform the user about keywords which aren't used
608699
raise ValueError("cbar_ax and cbar_kwargs can't be used with "

xarray/plot/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import numpy as np
77
import pandas as pd
88

9+
from inspect import getfullargspec
10+
911
from ..core.options import OPTIONS
1012
from ..core.utils import is_scalar
1113

xarray/tests/test_cftimeindex.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,26 @@ def test_cftimeindex_sub_cftimeindex(calendar):
700700
assert isinstance(result, pd.TimedeltaIndex)
701701

702702

703+
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
704+
@pytest.mark.parametrize('calendar', _CFTIME_CALENDARS)
705+
def test_cftimeindex_sub_cftime_datetime(calendar):
706+
a = xr.cftime_range('2000', periods=5, calendar=calendar)
707+
result = a - a[0]
708+
expected = pd.TimedeltaIndex([timedelta(days=i) for i in range(5)])
709+
assert result.equals(expected)
710+
assert isinstance(result, pd.TimedeltaIndex)
711+
712+
713+
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
714+
@pytest.mark.parametrize('calendar', _CFTIME_CALENDARS)
715+
def test_cftime_datetime_sub_cftimeindex(calendar):
716+
a = xr.cftime_range('2000', periods=5, calendar=calendar)
717+
result = a[0] - a
718+
expected = pd.TimedeltaIndex([timedelta(days=-i) for i in range(5)])
719+
assert result.equals(expected)
720+
assert isinstance(result, pd.TimedeltaIndex)
721+
722+
703723
@pytest.mark.skipif(not has_cftime, reason='cftime not installed')
704724
@pytest.mark.parametrize('calendar', _CFTIME_CALENDARS)
705725
def test_cftimeindex_sub_timedeltaindex(calendar):

xarray/tests/test_plot.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import numpy as np
55
import pandas as pd
66
import pytest
7+
from numpy.testing import assert_array_equal
78

89
import xarray as xr
910
import xarray.plot as xplt
@@ -140,6 +141,20 @@ def test_1d_x_y_kw(self):
140141
with raises_regex(ValueError, 'None'):
141142
da.plot(x='z', y='f')
142143

144+
# Test for bug in GH issue #2725
145+
def test_infer_line_data(self):
146+
current = DataArray(name='I', data=np.array([5, 8]), dims=['t'],
147+
coords={'t': (['t'], np.array([0.1, 0.2])),
148+
'V': (['t'], np.array([100, 200]))})
149+
150+
# Plot current against voltage
151+
line = current.plot.line(x='V')[0]
152+
assert_array_equal(line.get_xdata(), current.coords['V'].values)
153+
154+
# Plot current against time
155+
line = current.plot.line()[0]
156+
assert_array_equal(line.get_xdata(), current.coords['t'].values)
157+
143158
def test_2d_line(self):
144159
with raises_regex(ValueError, 'hue'):
145160
self.darray[:, :, 0].plot.line()

0 commit comments

Comments
 (0)