From c48254843fed2e3d871144727571bb3db2c194b1 Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Sat, 2 Mar 2019 18:48:16 -0800 Subject: [PATCH 1/4] BUG-24971 copying blocks also considers ndim --- doc/source/whatsnew/v0.24.2.rst | 2 +- pandas/core/internals/blocks.py | 2 +- pandas/tests/series/test_constructors.py | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst index 4fcde7769b362..8d62994c8181d 100644 --- a/doc/source/whatsnew/v0.24.2.rst +++ b/doc/source/whatsnew/v0.24.2.rst @@ -66,7 +66,7 @@ Bug Fixes **Categorical** -- +- Bug where a copy of a categorical could have the wrong dimensions (:issue:`24971`) - - diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 4e2c04dba8b04..d23a2a1224e16 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -738,7 +738,7 @@ def copy(self, deep=True): values = self.values if deep: values = values.copy() - return self.make_block_same_class(values) + return self.make_block_same_class(values, ndim=self.ndim) def replace(self, to_replace, value, inplace=False, filter=None, regex=False, convert=True): diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index d92ca48751d0a..17f522fe173e3 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -14,7 +14,7 @@ from pandas.compat import PY36, long, lrange, range, zip from pandas.core.dtypes.common import ( - is_categorical_dtype, is_datetime64tz_dtype) + is_categorical_dtype, is_datetime64tz_dtype, is_list_like) import pandas as pd from pandas import ( @@ -532,6 +532,11 @@ def test_constructor_copy(self): assert x[0] == 2. assert y[0] == 1. + def test_copy_categorical_ndim(self): + # GH 24971 + s = Series(Categorical(['A'], categories=['A'])) + assert not is_list_like(s.replace({'A': 1})[0]) + @pytest.mark.parametrize( "index", [ From 3cfd8089f25487a2dabe87d1ddabcd34c0bfaabe Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Sat, 2 Mar 2019 19:38:40 -0800 Subject: [PATCH 2/4] BUG-24971 clarify whatsnew and move tests --- doc/source/whatsnew/v0.24.2.rst | 2 +- pandas/tests/series/test_constructors.py | 7 +------ pandas/tests/series/test_replace.py | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst index 8d62994c8181d..ed3565262467c 100644 --- a/doc/source/whatsnew/v0.24.2.rst +++ b/doc/source/whatsnew/v0.24.2.rst @@ -66,7 +66,7 @@ Bug Fixes **Categorical** -- Bug where a copy of a categorical could have the wrong dimensions (:issue:`24971`) +- Bug where calling :meth:`Series.replace` on categorical data could return a ``Series`` with incorrect dimensions (:issue:`24971`) - - diff --git a/pandas/tests/series/test_constructors.py b/pandas/tests/series/test_constructors.py index 17f522fe173e3..d92ca48751d0a 100644 --- a/pandas/tests/series/test_constructors.py +++ b/pandas/tests/series/test_constructors.py @@ -14,7 +14,7 @@ from pandas.compat import PY36, long, lrange, range, zip from pandas.core.dtypes.common import ( - is_categorical_dtype, is_datetime64tz_dtype, is_list_like) + is_categorical_dtype, is_datetime64tz_dtype) import pandas as pd from pandas import ( @@ -532,11 +532,6 @@ def test_constructor_copy(self): assert x[0] == 2. assert y[0] == 1. - def test_copy_categorical_ndim(self): - # GH 24971 - s = Series(Categorical(['A'], categories=['A'])) - assert not is_list_like(s.replace({'A': 1})[0]) - @pytest.mark.parametrize( "index", [ diff --git a/pandas/tests/series/test_replace.py b/pandas/tests/series/test_replace.py index 40b28047080da..7a7235babbcd3 100644 --- a/pandas/tests/series/test_replace.py +++ b/pandas/tests/series/test_replace.py @@ -280,3 +280,17 @@ def test_replace_mixed_types_with_string(self): result = s.replace([2, '4'], np.nan) expected = pd.Series([1, np.nan, 3, np.nan, 4, 5]) tm.assert_series_equal(expected, result) + + @pytest.mark.parametrize("categorical, numeric", [ + (pd.Categorical('A', categories=['A', 'B']), [1]), + (pd.Categorical(('A', ), categories=['A', 'B']), [1]), + (pd.Categorical(('A', 'B'), categories=['A', 'B']), [1, 2]), + ]) + def test_copy_categorical_ndim(self, categorical, numeric): + # GH 24971 + s = pd.Series(categorical) + result = s.replace({'A': 1, 'B': 2}) + expected = pd.Series(numeric) + print(result.dtype) + print(expected.dtype) + tm.assert_series_equal(expected, result, check_dtype=False) From e22d67ce37f52ab6c477585ee213254b94fc1edb Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Mon, 4 Mar 2019 12:14:15 -0800 Subject: [PATCH 3/4] fix test --- pandas/tests/series/test_replace.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/pandas/tests/series/test_replace.py b/pandas/tests/series/test_replace.py index 7a7235babbcd3..4c5210f1c61b0 100644 --- a/pandas/tests/series/test_replace.py +++ b/pandas/tests/series/test_replace.py @@ -291,6 +291,4 @@ def test_copy_categorical_ndim(self, categorical, numeric): s = pd.Series(categorical) result = s.replace({'A': 1, 'B': 2}) expected = pd.Series(numeric) - print(result.dtype) - print(expected.dtype) tm.assert_series_equal(expected, result, check_dtype=False) From 6c75e7771a548c6ec3c4051d5dae9a1d8164764b Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Mon, 4 Mar 2019 14:20:44 -0800 Subject: [PATCH 4/4] rename test and add message --- pandas/tests/series/test_replace.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/tests/series/test_replace.py b/pandas/tests/series/test_replace.py index 4c5210f1c61b0..af113e79b3999 100644 --- a/pandas/tests/series/test_replace.py +++ b/pandas/tests/series/test_replace.py @@ -286,8 +286,10 @@ def test_replace_mixed_types_with_string(self): (pd.Categorical(('A', ), categories=['A', 'B']), [1]), (pd.Categorical(('A', 'B'), categories=['A', 'B']), [1, 2]), ]) - def test_copy_categorical_ndim(self, categorical, numeric): + def test_replace_categorical(self, categorical, numeric): # GH 24971 + # Do not check if dtypes are equal due to a known issue that + # Categorical.replace sometimes coerces to object (GH 23305) s = pd.Series(categorical) result = s.replace({'A': 1, 'B': 2}) expected = pd.Series(numeric)