From 6bef1afbeb646a02b9c34be7ec0d6bbb70bbac41 Mon Sep 17 00:00:00 2001 From: Stephan Hoyer Date: Sat, 11 Nov 2017 22:02:50 -0800 Subject: [PATCH] Validate shape of DataArray coords with same name as dimensions Fixes GH1709 --- doc/whats-new.rst | 4 ++++ xarray/core/dataarray.py | 12 +++++++++--- xarray/core/variable.py | 2 +- xarray/tests/test_dataarray.py | 3 +++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 668e70a42d9..1c6dfba138e 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -54,6 +54,10 @@ Bug fixes (:issue:`1697`). By `Stephan Hoyer `_. +- Validate the shape of coordinates with names matching dimensions in the + DataArray constructor (:issue:`1709`). + By `Stephan Hoyer `_. + Testing ~~~~~~~ diff --git a/xarray/core/dataarray.py b/xarray/core/dataarray.py index 1dac72335d2..0516b473994 100644 --- a/xarray/core/dataarray.py +++ b/xarray/core/dataarray.py @@ -35,7 +35,7 @@ def _infer_coords_and_dims(shape, coords, dims): """All the logic for creating a new DataArray""" if (coords is not None and not utils.is_dict_like(coords) and - len(coords) != len(shape)): + len(coords) != len(shape)): raise ValueError('coords is not dict-like, but it has %s items, ' 'which does not match the %s dimensions of the ' 'data' % (len(coords), len(shape))) @@ -50,8 +50,8 @@ def _infer_coords_and_dims(shape, coords, dims): if utils.is_dict_like(coords): # deprecated in GH993, removed in GH1539 raise ValueError('inferring DataArray dimensions from ' - 'dictionary like ``coords`` has been ' - 'deprecated. Use an explicit list of ' + 'dictionary like ``coords`` is no longer ' + 'supported. Use an explicit list of ' '``dims`` instead.') for n, (dim, coord) in enumerate(zip(dims, coords)): coord = as_variable(coord, @@ -87,6 +87,12 @@ def _infer_coords_and_dims(shape, coords, dims): 'length %s on the data but length %s on ' 'coordinate %r' % (d, sizes[d], s, k)) + if k in sizes and v.shape != (sizes[k],): + raise ValueError('coordinate %r is a DataArray dimension, but ' + 'it has shape %r rather than expected shape %r ' + 'matching the dimension size' + % (k, v.shape, (sizes[k],))) + assert_unique_multiindex_level_names(new_coords) return new_coords, dims diff --git a/xarray/core/variable.py b/xarray/core/variable.py index aa64dcab1fc..f2bc004c668 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -96,7 +96,7 @@ def as_variable(obj, name=None): '{}'.format(obj)) elif utils.is_scalar(obj): obj = Variable([], obj) - elif (isinstance(obj, (pd.Index, IndexVariable)) and obj.name is not None): + elif isinstance(obj, (pd.Index, IndexVariable)) and obj.name is not None: obj = Variable(obj.name, obj) elif name is not None: data = as_compatible_data(obj) diff --git a/xarray/tests/test_dataarray.py b/xarray/tests/test_dataarray.py index d39232c04c8..c86f706f2ce 100644 --- a/xarray/tests/test_dataarray.py +++ b/xarray/tests/test_dataarray.py @@ -298,6 +298,9 @@ def test_constructor_invalid(self): DataArray(np.random.rand(4, 4), [('x', self.mindex), ('level_1', range(4))]) + with raises_regex(ValueError, 'matching the dimension size'): + DataArray(data, coords={'x': 0}, dims=['x', 'y']) + def test_constructor_from_self_described(self): data = [[-0.1, 21], [0, 2]] expected = DataArray(data,