From 2f500c81faf13ba35a8395bc336935207d5daab8 Mon Sep 17 00:00:00 2001 From: Ryan Abernathey Date: Thu, 6 Sep 2018 16:10:39 -0400 Subject: [PATCH 1/6] relax check on dimension ndim --- xarray/core/variable.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 8bd7225efc3..7b75d242985 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -105,13 +105,11 @@ def as_variable(obj, name=None): if name is not None and name in obj.dims: # convert the Variable into an Index - if obj.ndim != 1: - raise MissingDimensionsError( - '%r has more than 1-dimension and the same name as one of its ' - 'dimensions %r. xarray disallows such variables because they ' - 'conflict with the coordinates used to label ' - 'dimensions.' % (name, obj.dims)) - obj = obj.to_index_variable() + if obj.ndim == 1: + obj = obj.to_index_variable() + else: + pass + # TODO: do something else with multidimensional variables return obj From ce143d27ebb8483afb16d300b963fcc14e5fc6d3 Mon Sep 17 00:00:00 2001 From: Ryan Abernathey Date: Sat, 19 Jan 2019 14:37:50 +0000 Subject: [PATCH 2/6] resolve confliclts --- xarray/core/coordinates.py | 2 +- xarray/core/formatting.py | 3 ++- xarray/tests/test_dataset.py | 19 ++++++++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/xarray/core/coordinates.py b/xarray/core/coordinates.py index 820937dae6a..e5a697f171f 100644 --- a/xarray/core/coordinates.py +++ b/xarray/core/coordinates.py @@ -10,7 +10,7 @@ expand_and_merge_variables, merge_coords, merge_coords_for_inplace_math) from .pycompat import OrderedDict from .utils import Frozen, ReprObject, either_dict_or_kwargs -from .variable import Variable +from .variable import Variable, IndexVariable # Used as the key corresponding to a DataArray's variable when converting # arbitrary DataArray objects to datasets diff --git a/xarray/core/formatting.py b/xarray/core/formatting.py index 50fa64c9987..d3d4f51bccd 100644 --- a/xarray/core/formatting.py +++ b/xarray/core/formatting.py @@ -272,7 +272,8 @@ def summarize_datavar(name, var, col_width): def summarize_coord(name, var, col_width): - is_index = name in var.dims + from .variable import IndexVariable + is_index = name in var.dims and isinstance(var, IndexVariable) show_values = var._in_memory marker = u'*' if is_index else u' ' if is_index: diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index e55caf1bf13..615d0d6e0ac 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -237,9 +237,7 @@ def test_constructor(self): with raises_regex(ValueError, 'conflicting sizes'): Dataset({'a': x1, 'b': x2}) - with raises_regex(ValueError, "disallows such variables"): - Dataset({'a': x1, 'x': z}) - with raises_regex(TypeError, 'tuple of form'): + with raises_regex(TypeError, 'tuples of form'): Dataset({'x': (1, 2, 3, 4, 5, 6, 7)}) with raises_regex(ValueError, 'already exists as a scalar'): Dataset({'x': 0, 'y': ('x', [1, 2, 3])}) @@ -249,6 +247,21 @@ def test_constructor(self): actual = Dataset({'z': expected['z']}) assert_identical(expected, actual) + def test_constructor_multidim_dimensions(self): + # checks related to GH2368, GH2233 + ds = xr.Dataset({'a': ('x', 2 * np.arange(100)), + 'x': (['x', 'y'], np.arange(1000).reshape(100, 10))}) + + # dataset should have no indices + assert not isinstance(ds.variables['x'], IndexVariable) + assert len(ds.indexes) == 0 + assert 'x' not in ds.indexes + with pytest.raises(KeyError): + ds.indexes['x'] + + repr(ds) + repr(ds.indexes) + def test_constructor_invalid_dims(self): # regression for GH1120 with pytest.raises(MergeError): From 44e93d9e4ba93b2d9c2d83ceb7dc97e841f47df6 Mon Sep 17 00:00:00 2001 From: Ryan Abernathey Date: Sat, 19 Jan 2019 14:38:14 +0000 Subject: [PATCH 3/6] working onupdate --- xarray/core/indexes.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/xarray/core/indexes.py b/xarray/core/indexes.py index ffa483fc370..70f5e8b2343 100644 --- a/xarray/core/indexes.py +++ b/xarray/core/indexes.py @@ -35,6 +35,47 @@ def __getitem__(self, key): def __unicode__(self): return formatting.indexes_repr(self) +# class Indexes(Mapping, formatting.ReprMixin): +# """Ordered Mapping[str, pandas.Index] for xarray objects. +# """ +# +# def __init__(self, variables, sizes): +# """Not for public consumption. +# +# Parameters +# ---------- +# variables : OrderedDict[Any, Variable] +# Reference to OrderedDict holding variable objects. Should be the +# same dictionary used by the source object. +# sizes : OrderedDict[Any, int] +# Map from dimension names to sizes. +# """ +# self._variables = variables +# self._sizes = sizes +# +# def _is_index_variable(self, key): +# return (key in self._variables and key in self._sizes and +# isinstance(self._variables[key], IndexVariable)) +# +# def __iter__(self): +# for key in self._sizes: +# if self._is_index_variable(key): +# yield key +# +# def __len__(self): +# return sum(self._is_index_variable(key) for key in self._sizes) +# +# def __contains__(self, key): +# self._is_index_variable(key) +# +# def __getitem__(self, key): +# if not self._is_index_variable(key): +# raise KeyError(key) +# return self._variables[key].to_index() +# +# def __unicode__(self): +# return formatting.indexes_repr(self) + def default_indexes(coords, dims): """Default indexes for a Dataset/DataArray. From a4925b6398491b5249a6f3a81c1c22cf233b4317 Mon Sep 17 00:00:00 2001 From: Ryan Abernathey Date: Mon, 10 Sep 2018 14:08:30 -0400 Subject: [PATCH 4/6] fix formatting bug --- xarray/core/formatting.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xarray/core/formatting.py b/xarray/core/formatting.py index d3d4f51bccd..d182cc5e379 100644 --- a/xarray/core/formatting.py +++ b/xarray/core/formatting.py @@ -273,7 +273,9 @@ def summarize_datavar(name, var, col_width): def summarize_coord(name, var, col_width): from .variable import IndexVariable - is_index = name in var.dims and isinstance(var, IndexVariable) + # is there a cleaner way to check if something is an index variable? + variable = getattr(var, 'variable', var) + is_index = name in var.dims and isinstance(variable, IndexVariable) show_values = var._in_memory marker = u'*' if is_index else u' ' if is_index: From 5f11232689daef682e36279cdc8ed72f418fa2af Mon Sep 17 00:00:00 2001 From: Ryan Abernathey Date: Sat, 19 Jan 2019 15:02:39 +0000 Subject: [PATCH 5/6] got old tests working --- xarray/core/indexes.py | 43 +----------------------------------- xarray/tests/test_dataset.py | 5 ++++- 2 files changed, 5 insertions(+), 43 deletions(-) diff --git a/xarray/core/indexes.py b/xarray/core/indexes.py index 70f5e8b2343..8ac37f03e4d 100644 --- a/xarray/core/indexes.py +++ b/xarray/core/indexes.py @@ -35,47 +35,6 @@ def __getitem__(self, key): def __unicode__(self): return formatting.indexes_repr(self) -# class Indexes(Mapping, formatting.ReprMixin): -# """Ordered Mapping[str, pandas.Index] for xarray objects. -# """ -# -# def __init__(self, variables, sizes): -# """Not for public consumption. -# -# Parameters -# ---------- -# variables : OrderedDict[Any, Variable] -# Reference to OrderedDict holding variable objects. Should be the -# same dictionary used by the source object. -# sizes : OrderedDict[Any, int] -# Map from dimension names to sizes. -# """ -# self._variables = variables -# self._sizes = sizes -# -# def _is_index_variable(self, key): -# return (key in self._variables and key in self._sizes and -# isinstance(self._variables[key], IndexVariable)) -# -# def __iter__(self): -# for key in self._sizes: -# if self._is_index_variable(key): -# yield key -# -# def __len__(self): -# return sum(self._is_index_variable(key) for key in self._sizes) -# -# def __contains__(self, key): -# self._is_index_variable(key) -# -# def __getitem__(self, key): -# if not self._is_index_variable(key): -# raise KeyError(key) -# return self._variables[key].to_index() -# -# def __unicode__(self): -# return formatting.indexes_repr(self) - def default_indexes(coords, dims): """Default indexes for a Dataset/DataArray. @@ -93,4 +52,4 @@ def default_indexes(coords, dims): to indexes used for indexing along that dimension. """ return OrderedDict((key, coords[key].to_index()) - for key in dims if key in coords) + for key in dims if key in coords and coords[key].ndim==1) diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 615d0d6e0ac..8a71bfe3212 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -237,7 +237,10 @@ def test_constructor(self): with raises_regex(ValueError, 'conflicting sizes'): Dataset({'a': x1, 'b': x2}) - with raises_regex(TypeError, 'tuples of form'): + # these are now allowed -- let's add a more explicit test + #with raises_regex(ValueError, "disallows such variables"): + # Dataset({'a': x1, 'x': z}) + with raises_regex(TypeError, 'tuple of form'): Dataset({'x': (1, 2, 3, 4, 5, 6, 7)}) with raises_regex(ValueError, 'already exists as a scalar'): Dataset({'x': 0, 'y': ('x', [1, 2, 3])}) From 40c8d36844fdee6f8c06ec5babfacb25f177e954 Mon Sep 17 00:00:00 2001 From: Ryan Abernathey Date: Sat, 19 Jan 2019 15:28:47 +0000 Subject: [PATCH 6/6] clean up formatting tests --- xarray/core/formatting.py | 5 +---- xarray/tests/test_dataset.py | 16 +++++++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/xarray/core/formatting.py b/xarray/core/formatting.py index d182cc5e379..f68076c0732 100644 --- a/xarray/core/formatting.py +++ b/xarray/core/formatting.py @@ -272,10 +272,7 @@ def summarize_datavar(name, var, col_width): def summarize_coord(name, var, col_width): - from .variable import IndexVariable - # is there a cleaner way to check if something is an index variable? - variable = getattr(var, 'variable', var) - is_index = name in var.dims and isinstance(variable, IndexVariable) + is_index = name in var.dims and var.ndim==1 show_values = var._in_memory marker = u'*' if is_index else u' ' if is_index: diff --git a/xarray/tests/test_dataset.py b/xarray/tests/test_dataset.py index 8a71bfe3212..5bc9489c553 100644 --- a/xarray/tests/test_dataset.py +++ b/xarray/tests/test_dataset.py @@ -60,6 +60,11 @@ def create_test_multiindex(): return Dataset({}, {'x': mindex}) +def create_test_multidim_coord_no_index(): + ds = xr.Dataset({'a': ('x', [1, 1]), + 'x': (['x', 'y'], [[1, 1, 1, 1], [2, 2, 2, 2]])}) + return ds + class InaccessibleVariableDataStore(backends.InMemoryDataStore): def __init__(self): super(InaccessibleVariableDataStore, self).__init__() @@ -176,6 +181,11 @@ def test_repr_period_index(self): # check that creating the repr doesn't raise an error #GH645 repr(data) + def test_repr_no_index_on_multidim_coord(self): + data = create_test_multidim_coord_no_index() + actual = repr(data) + assert '*' not in actual + def test_unicode_data(self): # regression test for GH834 data = Dataset({u'foø': [u'ba®']}, attrs={u'å': u'∑'}) @@ -252,8 +262,7 @@ def test_constructor(self): def test_constructor_multidim_dimensions(self): # checks related to GH2368, GH2233 - ds = xr.Dataset({'a': ('x', 2 * np.arange(100)), - 'x': (['x', 'y'], np.arange(1000).reshape(100, 10))}) + ds = create_test_multidim_coord_no_index() # dataset should have no indices assert not isinstance(ds.variables['x'], IndexVariable) @@ -262,9 +271,6 @@ def test_constructor_multidim_dimensions(self): with pytest.raises(KeyError): ds.indexes['x'] - repr(ds) - repr(ds.indexes) - def test_constructor_invalid_dims(self): # regression for GH1120 with pytest.raises(MergeError):