From e2e04cea6ab5a0c5e0b529e99424c0c63a2f4fef Mon Sep 17 00:00:00 2001 From: Phillip Cloud Date: Thu, 20 Feb 2014 23:38:42 -0500 Subject: [PATCH] BUG: punt to user when passing overlapping replacment values in a nested dict --- doc/source/release.rst | 2 ++ pandas/core/generic.py | 8 ++++++-- pandas/tests/test_frame.py | 13 +++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index e40f9c2826f99..322b05b8d8b31 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -164,6 +164,8 @@ Bug Fixes - ``eval``/``query`` expressions with strings containing the ``@`` character will now work (:issue:`6366`). - Bug in ``Series.reindex`` when specifying a ``method`` with some nan values was inconsistent (noted on a resample) (:issue:`6418`) +- Bug in :meth:`DataFrame.replace` where nested dicts were erroneously + depending on the order of dictionary keys and values (:issue:`5338`). pandas 0.13.1 ------------- diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 01bf5baf21161..8be4d7010c8ac 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -2327,8 +2327,12 @@ def replace(self, to_replace=None, value=None, inplace=False, limit=None, value_dict = {} for k, v in items: - to_rep_dict[k] = list(v.keys()) - value_dict[k] = list(v.values()) + keys, values = zip(*v.items()) + if set(keys) & set(values): + raise ValueError("Replacement not allowed with " + "overlapping keys and values") + to_rep_dict[k] = list(keys) + value_dict[k] = list(values) to_replace, value = to_rep_dict, value_dict else: diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 88cf3179b33f2..73192b41784cd 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -8089,6 +8089,19 @@ def test_replace_with_dict_with_bool_keys(self): with tm.assertRaisesRegexp(TypeError, 'Cannot compare types .+'): df.replace({'asdf': 'asdb', True: 'yes'}) + def test_replace_int_to_int_chain(self): + df = DataFrame({'a': lrange(1, 5)}) + with tm.assertRaisesRegexp(ValueError, "Replacement not allowed .+"): + df.replace({'a': dict(zip(range(1, 5), range(2, 6)))}) + + def test_replace_str_to_str_chain(self): + a = np.arange(1, 5) + astr = a.astype(str) + bstr = np.arange(2, 6).astype(str) + df = DataFrame({'a': astr}) + with tm.assertRaisesRegexp(ValueError, "Replacement not allowed .+"): + df.replace({'a': dict(zip(astr, bstr))}) + def test_combine_multiple_frames_dtypes(self): # GH 2759