From 5362a7c5d2183e7fc00f62ea5c5ae6b73dbe2a83 Mon Sep 17 00:00:00 2001 From: Benoit Bovy Date: Mon, 13 Jun 2016 12:19:36 +0200 Subject: [PATCH 1/2] fix variable index copy --- doc/whats-new.rst | 3 +++ xarray/core/variable.py | 6 +++++- xarray/test/test_variable.py | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/whats-new.rst b/doc/whats-new.rst index 43dc6670daf..bd74277ccf0 100644 --- a/doc/whats-new.rst +++ b/doc/whats-new.rst @@ -67,6 +67,9 @@ Bug fixes This fixes issue :issue:`665`. `Filipe Fernandes `_. +- ``Variable.copy(deep=True)`` no longer converts MultiIndex into a base Index + (:issue:`769`). By `Benoit Bovy `_. + .. _whats-new.0.7.2: v0.7.2 (13 March 2016) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index 1ac9e2746a8..c9c861bc80c 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -410,7 +410,11 @@ def copy(self, deep=True): If `deep=True`, the data array is loaded into memory and copied onto the new object. Dimensions, attributes and encodings are always copied. """ - if deep and not isinstance(self.data, dask_array_type): + if isinstance(self._data, PandasIndexAdapter): + # there is no need to copy the index values here even if deep=True + # since pandas.Index objects are immutable + data = PandasIndexAdapter(self) if deep else self._data + elif deep and not isinstance(self.data, dask_array_type): # dask arrays don't have a copy method # https://github.com/blaze/dask/issues/911 data = self.data.copy() diff --git a/xarray/test/test_variable.py b/xarray/test/test_variable.py index 78cbaf41eff..776099e7597 100644 --- a/xarray/test/test_variable.py +++ b/xarray/test/test_variable.py @@ -383,6 +383,15 @@ def test_copy(self): source_ndarray(w.values)) self.assertVariableIdentical(v, copy(v)) + def test_copy_index(self): + midx = pd.MultiIndex.from_product([['a', 'b'], [1, 2], [-1, -2]], + names=('one', 'two', 'three')) + v = self.cls('x', midx) + for deep in [True, False]: + w = v.copy(deep=deep) + self.assertIsInstance(w._data, PandasIndexAdapter) + self.assertIs(v._data.array, w._data.array) + def test_real_and_imag(self): v = self.cls('x', np.arange(3) - 1j * np.arange(3), {'foo': 'bar'}) expected_re = self.cls('x', np.arange(3), {'foo': 'bar'}) From 9ea8832959a54fed81e7194c18cc024ba0fe9bd1 Mon Sep 17 00:00:00 2001 From: Benoit Bovy Date: Tue, 14 Jun 2016 10:55:59 +0200 Subject: [PATCH 2/2] no need to create a new PandasIndexAdapter object --- xarray/core/variable.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/xarray/core/variable.py b/xarray/core/variable.py index c9c861bc80c..c877b216273 100644 --- a/xarray/core/variable.py +++ b/xarray/core/variable.py @@ -410,11 +410,9 @@ def copy(self, deep=True): If `deep=True`, the data array is loaded into memory and copied onto the new object. Dimensions, attributes and encodings are always copied. """ - if isinstance(self._data, PandasIndexAdapter): - # there is no need to copy the index values here even if deep=True - # since pandas.Index objects are immutable - data = PandasIndexAdapter(self) if deep else self._data - elif deep and not isinstance(self.data, dask_array_type): + if (deep and not isinstance(self.data, dask_array_type) + and not isinstance(self._data, PandasIndexAdapter)): + # pandas.Index objects are immutable # dask arrays don't have a copy method # https://github.com/blaze/dask/issues/911 data = self.data.copy()