From fe1f3ad43d2eab46279a4a84087da41810de63c3 Mon Sep 17 00:00:00 2001 From: David Krych Date: Wed, 7 Feb 2018 14:50:42 -0500 Subject: [PATCH 01/12] ENH: Allow literal (non-regex) replacement using .str.replace #16808 --- pandas/core/strings.py | 81 +++++++++++++++++++++++------------- pandas/tests/test_strings.py | 14 +++++++ 2 files changed, 65 insertions(+), 30 deletions(-) diff --git a/pandas/core/strings.py b/pandas/core/strings.py index b1c1ede66236c..92e3226af76c2 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -305,7 +305,7 @@ def str_endswith(arr, pat, na=np.nan): return _na_map(f, arr, na, dtype=bool) -def str_replace(arr, pat, repl, n=-1, case=None, flags=0): +def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): r""" Replace occurrences of pattern/regex in the Series/Index with some other string. Equivalent to :meth:`str.replace` or @@ -336,6 +336,11 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0): flags : int, default 0 (no flags) - re module flags, e.g. re.IGNORECASE - Cannot be set if `pat` is a compiled regex + regex : boolean, default True + - If True, assumes the passed-in pattern is a regular expression. + - If False, treats the pattern as a literal string + - Cannot be set to False if `pat` is a compiled regex or `repl` is + a callable. Returns ------- @@ -344,17 +349,27 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0): Notes ----- When `pat` is a compiled regex, all flags should be included in the - compiled regex. Use of `case` or `flags` with a compiled regex will - raise an error. + compiled regex. Use of `case`, `flags`, or `regex` with a compiled regex + will raise an error. Examples -------- - When `repl` is a string, every `pat` is replaced as with - :meth:`str.replace`. NaN value(s) in the Series are left as is. + When `pat` is a string and `regex` is False, every `pat` is replaced with + `repl` as with :meth:`str.replace`. NaN value(s) in the Series are left as + is. - >>> pd.Series(['foo', 'fuz', np.nan]).str.replace('f', 'b') - 0 boo - 1 buz + >>> pd.Series(['f.o', 'fuz', np.nan]).str.replace('f.', 'ba', regex=False) + 0 bao + 1 fuz + 2 NaN + dtype: object + + When `pat` is a string and `regex` is True, the given `pat` is compiled + as a regex. When `repl` is a string, it replaces matching regex patterns + literally as with :meth:`re.sub`: + >>> pd.Series(['foo', 'fuz', np.nan]).str.replace('f.', 'ba', regex=True) + 0 bao + 1 baz 2 NaN dtype: object @@ -403,27 +418,33 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0): raise TypeError("repl must be a string or callable") is_compiled_re = is_re(pat) - if is_compiled_re: - if (case is not None) or (flags != 0): - raise ValueError("case and flags cannot be set" - " when pat is a compiled regex") - else: - # not a compiled regex - # set default case - if case is None: - case = True - - # add case flag, if provided - if case is False: - flags |= re.IGNORECASE - - use_re = is_compiled_re or len(pat) > 1 or flags or callable(repl) - - if use_re: - n = n if n >= 0 else 0 - regex = re.compile(pat, flags=flags) - f = lambda x: regex.sub(repl=repl, string=x, count=n) + if regex: + if is_compiled_re: + if (case is not None) or (flags != 0): + raise ValueError("case and flags cannot be set" + " when pat is a compiled regex") + else: + # not a compiled regex + # set default case + if case is None: + case = True + + # add case flag, if provided + if case is False: + flags |= re.IGNORECASE + if is_compiled_re or len(pat) > 1 or flags or callable(repl): + n = n if n >= 0 else 0 + compiled = re.compile(pat, flags=flags) + f = lambda x: compiled.sub(repl=repl, string=x, count=n) + else: + f = lambda x: x.replace(pat, repl, n) else: + if is_compiled_re: + raise ValueError("Cannot use a compiled regex as replacement " + "pattern with regex=False") + if callable(repl): + raise ValueError("Cannot use a callable replacement when " + "regex=False") f = lambda x: x.replace(pat, repl, n) return _na_map(f, arr) @@ -1595,9 +1616,9 @@ def match(self, pat, case=True, flags=0, na=np.nan, as_indexer=None): return self._wrap_result(result) @copy(str_replace) - def replace(self, pat, repl, n=-1, case=None, flags=0): + def replace(self, pat, repl, n=-1, case=None, flags=0, regex=True): result = str_replace(self._data, pat, repl, n=n, case=case, - flags=flags) + flags=flags, regex=regex) return self._wrap_result(result) @copy(str_repeat) diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index 178c5ff655b04..1c06f807cb64f 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -431,6 +431,16 @@ def test_replace(self): values = klass(data) pytest.raises(TypeError, values.str.replace, 'a', repl) + # GH16808 literal replace (regex=False vs regex=True) + values = Series(['f.o', 'foo', NA]) + exp = Series(['bao', 'bao', NA]) + result = values.str.replace('f.', 'ba') + tm.assert_series_equal(result, exp) + + exp = Series(['bao', 'foo', NA]) + result = values.str.replace('f.', 'ba', regex=False) + tm.assert_series_equal(result, exp) + def test_replace_callable(self): # GH 15055 values = Series(['fooBAD__barBAD', NA]) @@ -441,6 +451,8 @@ def test_replace_callable(self): exp = Series(['foObaD__baRbaD', NA]) tm.assert_series_equal(result, exp) + pytest.raises(ValueError, values.str.replace, 'abc', repl, regex=False) + # test with wrong number of arguments, raising an error if compat.PY2: p_err = r'takes (no|(exactly|at (least|most)) ?\d+) arguments?' @@ -522,6 +534,8 @@ def test_replace_compiled_regex(self): "case and flags cannot be"): result = values.str.replace(pat, '', case=True) + pytest.raises(ValueError, values.str.replace, pat, '', regex=False) + # test with callable values = Series(['fooBAD__barBAD', NA]) repl = lambda m: m.group(0).swapcase() From d53cf86d8a34c9c64eb4a2bfb3e03ba97b91d476 Mon Sep 17 00:00:00 2001 From: David Krych Date: Mon, 12 Feb 2018 12:21:36 -0500 Subject: [PATCH 02/12] Add versionadded tag to regex param docstring. --- pandas/core/strings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/core/strings.py b/pandas/core/strings.py index 92e3226af76c2..4357a7e422961 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -342,6 +342,8 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): - Cannot be set to False if `pat` is a compiled regex or `repl` is a callable. + .. versionadded:: 0.23.0 + Returns ------- replaced : Series/Index of objects From 656fd689c2829908fa5e761fd796bba2616bae13 Mon Sep 17 00:00:00 2001 From: David Krych Date: Mon, 12 Feb 2018 12:44:59 -0500 Subject: [PATCH 03/12] Move GH16808 tests to their own method. --- pandas/tests/test_strings.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index 1c06f807cb64f..2bf438e38dd99 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -431,16 +431,6 @@ def test_replace(self): values = klass(data) pytest.raises(TypeError, values.str.replace, 'a', repl) - # GH16808 literal replace (regex=False vs regex=True) - values = Series(['f.o', 'foo', NA]) - exp = Series(['bao', 'bao', NA]) - result = values.str.replace('f.', 'ba') - tm.assert_series_equal(result, exp) - - exp = Series(['bao', 'foo', NA]) - result = values.str.replace('f.', 'ba', regex=False) - tm.assert_series_equal(result, exp) - def test_replace_callable(self): # GH 15055 values = Series(['fooBAD__barBAD', NA]) @@ -451,8 +441,6 @@ def test_replace_callable(self): exp = Series(['foObaD__baRbaD', NA]) tm.assert_series_equal(result, exp) - pytest.raises(ValueError, values.str.replace, 'abc', repl, regex=False) - # test with wrong number of arguments, raising an error if compat.PY2: p_err = r'takes (no|(exactly|at (least|most)) ?\d+) arguments?' @@ -534,8 +522,6 @@ def test_replace_compiled_regex(self): "case and flags cannot be"): result = values.str.replace(pat, '', case=True) - pytest.raises(ValueError, values.str.replace, pat, '', regex=False) - # test with callable values = Series(['fooBAD__barBAD', NA]) repl = lambda m: m.group(0).swapcase() @@ -544,6 +530,24 @@ def test_replace_compiled_regex(self): exp = Series(['foObaD__baRbaD', NA]) tm.assert_series_equal(result, exp) + def test_replace_literal(self): + # GH16808 literal replace (regex=False vs regex=True) + values = Series(['f.o', 'foo', NA]) + exp = Series(['bao', 'bao', NA]) + result = values.str.replace('f.', 'ba') + tm.assert_series_equal(result, exp) + + exp = Series(['bao', 'foo', NA]) + result = values.str.replace('f.', 'ba', regex=False) + tm.assert_series_equal(result, exp) + + # Cannot do a literal replace if given a callable repl or compiled pattern + callable_repl = lambda m: m.group(0).swapcase() + compiled_pat = re.compile('[a-z][A-Z]{2}') + + pytest.raises(ValueError, values.str.replace, 'abc', callable_repl, regex=False) + pytest.raises(ValueError, values.str.replace, compiled_pat, '', regex=False) + def test_repeat(self): values = Series(['a', 'b', NA, 'c', NA, 'd']) From a28ef8fbdcc8d846dc0194d6b3fee8b4024e7012 Mon Sep 17 00:00:00 2001 From: David Krych Date: Mon, 12 Feb 2018 13:02:45 -0500 Subject: [PATCH 04/12] Fix PEP8 line length in tests. --- pandas/tests/test_strings.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index 2bf438e38dd99..a878d6ed7b052 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -541,12 +541,15 @@ def test_replace_literal(self): result = values.str.replace('f.', 'ba', regex=False) tm.assert_series_equal(result, exp) - # Cannot do a literal replace if given a callable repl or compiled pattern + # Cannot do a literal replace if given a callable repl or compiled + # pattern callable_repl = lambda m: m.group(0).swapcase() compiled_pat = re.compile('[a-z][A-Z]{2}') - pytest.raises(ValueError, values.str.replace, 'abc', callable_repl, regex=False) - pytest.raises(ValueError, values.str.replace, compiled_pat, '', regex=False) + pytest.raises(ValueError, values.str.replace, 'abc', callable_repl, + regex=False) + pytest.raises(ValueError, values.str.replace, compiled_pat, '', + regex=False) def test_repeat(self): values = Series(['a', 'b', NA, 'c', NA, 'd']) From c5325ae08eb1e4ac2798b08d47342f1d05f2d827 Mon Sep 17 00:00:00 2001 From: David Krych Date: Mon, 12 Feb 2018 16:31:55 -0500 Subject: [PATCH 05/12] Documentation additions/fixes. --- doc/source/text.rst | 28 +++++++++++++++++++++------- doc/source/whatsnew/v0.23.0.txt | 1 + pandas/core/strings.py | 3 ++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/doc/source/text.rst b/doc/source/text.rst index 1e620acb1f88a..047be960cd10e 100644 --- a/doc/source/text.rst +++ b/doc/source/text.rst @@ -118,8 +118,8 @@ i.e., from the end of the string to the beginning of the string: s2.str.rsplit('_', expand=True, n=1) -Methods like ``replace`` and ``findall`` take `regular expressions -`__, too: +``replace`` by default replaces `regular expressions +`__: .. ipython:: python @@ -146,12 +146,25 @@ following code will cause trouble because of the regular expression meaning of # We need to escape the special character (for >1 len patterns) dollars.str.replace(r'-\$', '-') +.. versionadded:: 0.23.0 + +If you do want literal replacement of a string (equivalent to +:meth:`str.replace`), you can set the optional ``regex`` parameter to +``False``, rather than escaping each character. In this case both ``pat`` +and ``repl`` must be strings: + +.. ipython:: python + + # These lines are equivalent + dollars.str.replace(r'-\$', '-') + dollars.str.replace('-$', '-', regex=False) + +.. versionadded:: 0.20.0 + The ``replace`` method can also take a callable as replacement. It is called on every ``pat`` using :func:`re.sub`. The callable should expect one positional argument (a regex object) and return a string. -.. versionadded:: 0.20.0 - .. ipython:: python # Reverse every lowercase alphabetic word @@ -164,12 +177,12 @@ positional argument (a regex object) and return a string. repl = lambda m: m.group('two').swapcase() pd.Series(['Foo Bar Baz', np.nan]).str.replace(pat, repl) +.. versionadded:: 0.20.0 + The ``replace`` method also accepts a compiled regular expression object from :func:`re.compile` as a pattern. All flags should be included in the compiled regular expression object. -.. versionadded:: 0.20.0 - .. ipython:: python import re @@ -186,6 +199,7 @@ regular expression object will raise a ``ValueError``. --------------------------------------------------------------------------- ValueError: case and flags cannot be set when pat is a compiled regex + Indexing with ``.str`` ---------------------- @@ -432,7 +446,7 @@ Method Summary :meth:`~Series.str.join`;Join strings in each element of the Series with passed separator :meth:`~Series.str.get_dummies`;Split strings on the delimiter returning DataFrame of dummy variables :meth:`~Series.str.contains`;Return boolean array if each string contains pattern/regex - :meth:`~Series.str.replace`;Replace occurrences of pattern/regex with some other string or the return value of a callable given the occurrence + :meth:`~Series.str.replace`;Replace occurrences of pattern/regex/string with some other string or the return value of a callable given the occurrence :meth:`~Series.str.repeat`;Duplicate values (``s.str.repeat(3)`` equivalent to ``x * 3``) :meth:`~Series.str.pad`;"Add whitespace to left, right, or both sides of strings" :meth:`~Series.str.center`;Equivalent to ``str.center`` diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 5330f7e7e998b..a166f32ba3e09 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -620,6 +620,7 @@ Other API Changes - Set operations (union, difference...) on :class:`IntervalIndex` with incompatible index types will now raise a ``TypeError`` rather than a ``ValueError`` (:issue:`19329`) - :class:`DateOffset` objects render more simply, e.g. ```` instead of ```` (:issue:`19403`) - ``Categorical.fillna`` now validates its ``value`` and ``method`` keyword arguments. It now raises when both or none are specified, matching the behavior of :meth:`Series.fillna` (:issue:`19682`) +- :func:`Series.str.replace` now takes an optional `regex` keyword which, when set to ``False``, uses literal string replacement rather than regex replacement (:issue:`16808`) .. _whatsnew_0230.deprecations: diff --git a/pandas/core/strings.py b/pandas/core/strings.py index 4357a7e422961..a8eb0c07b0f0f 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -368,7 +368,8 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): When `pat` is a string and `regex` is True, the given `pat` is compiled as a regex. When `repl` is a string, it replaces matching regex patterns - literally as with :meth:`re.sub`: + as with :meth:`re.sub`: + >>> pd.Series(['foo', 'fuz', np.nan]).str.replace('f.', 'ba', regex=True) 0 bao 1 baz From a98bd343dac4aa187f9bbd5227cfd675e8d39e9e Mon Sep 17 00:00:00 2001 From: David Krych Date: Tue, 13 Feb 2018 15:34:12 -0500 Subject: [PATCH 06/12] Clarify it is "regex=False" that does not work with compiled regex. --- pandas/core/strings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/strings.py b/pandas/core/strings.py index a8eb0c07b0f0f..9969117a7e02f 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -351,8 +351,8 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): Notes ----- When `pat` is a compiled regex, all flags should be included in the - compiled regex. Use of `case`, `flags`, or `regex` with a compiled regex - will raise an error. + compiled regex. Use of `case`, `flags`, or `regex=False` with a compiled + regex will raise an error. Examples -------- From 09c1c9faf9c2cb1aeece8362bbd7d866c1ebd767 Mon Sep 17 00:00:00 2001 From: David Krych Date: Wed, 7 Feb 2018 14:50:42 -0500 Subject: [PATCH 07/12] ENH: Allow literal (non-regex) replacement using .str.replace #16808 --- pandas/tests/test_strings.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index a878d6ed7b052..3ca7fbac3af7c 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -431,6 +431,16 @@ def test_replace(self): values = klass(data) pytest.raises(TypeError, values.str.replace, 'a', repl) + # GH16808 literal replace (regex=False vs regex=True) + values = Series(['f.o', 'foo', NA]) + exp = Series(['bao', 'bao', NA]) + result = values.str.replace('f.', 'ba') + tm.assert_series_equal(result, exp) + + exp = Series(['bao', 'foo', NA]) + result = values.str.replace('f.', 'ba', regex=False) + tm.assert_series_equal(result, exp) + def test_replace_callable(self): # GH 15055 values = Series(['fooBAD__barBAD', NA]) @@ -441,6 +451,8 @@ def test_replace_callable(self): exp = Series(['foObaD__baRbaD', NA]) tm.assert_series_equal(result, exp) + pytest.raises(ValueError, values.str.replace, 'abc', repl, regex=False) + # test with wrong number of arguments, raising an error if compat.PY2: p_err = r'takes (no|(exactly|at (least|most)) ?\d+) arguments?' @@ -522,6 +534,8 @@ def test_replace_compiled_regex(self): "case and flags cannot be"): result = values.str.replace(pat, '', case=True) + pytest.raises(ValueError, values.str.replace, pat, '', regex=False) + # test with callable values = Series(['fooBAD__barBAD', NA]) repl = lambda m: m.group(0).swapcase() From 866db2fcd4d2dc68a4807167eb05c03bbd939e76 Mon Sep 17 00:00:00 2001 From: David Krych Date: Mon, 12 Feb 2018 12:44:59 -0500 Subject: [PATCH 08/12] Move GH16808 tests to their own method. --- pandas/tests/test_strings.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index 3ca7fbac3af7c..a878d6ed7b052 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -431,16 +431,6 @@ def test_replace(self): values = klass(data) pytest.raises(TypeError, values.str.replace, 'a', repl) - # GH16808 literal replace (regex=False vs regex=True) - values = Series(['f.o', 'foo', NA]) - exp = Series(['bao', 'bao', NA]) - result = values.str.replace('f.', 'ba') - tm.assert_series_equal(result, exp) - - exp = Series(['bao', 'foo', NA]) - result = values.str.replace('f.', 'ba', regex=False) - tm.assert_series_equal(result, exp) - def test_replace_callable(self): # GH 15055 values = Series(['fooBAD__barBAD', NA]) @@ -451,8 +441,6 @@ def test_replace_callable(self): exp = Series(['foObaD__baRbaD', NA]) tm.assert_series_equal(result, exp) - pytest.raises(ValueError, values.str.replace, 'abc', repl, regex=False) - # test with wrong number of arguments, raising an error if compat.PY2: p_err = r'takes (no|(exactly|at (least|most)) ?\d+) arguments?' @@ -534,8 +522,6 @@ def test_replace_compiled_regex(self): "case and flags cannot be"): result = values.str.replace(pat, '', case=True) - pytest.raises(ValueError, values.str.replace, pat, '', regex=False) - # test with callable values = Series(['fooBAD__barBAD', NA]) repl = lambda m: m.group(0).swapcase() From d0dfc6a631010deff4ca0c79ff0d3e75b5e0ced6 Mon Sep 17 00:00:00 2001 From: David Krych Date: Tue, 27 Feb 2018 14:15:11 -0500 Subject: [PATCH 09/12] Clarify documentation --- pandas/core/strings.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/pandas/core/strings.py b/pandas/core/strings.py index 9969117a7e02f..e1eccb5deffad 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -356,23 +356,23 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): Examples -------- - When `pat` is a string and `regex` is False, every `pat` is replaced with - `repl` as with :meth:`str.replace`. NaN value(s) in the Series are left as - is. + When `pat` is a string and `regex` is True (the default), the given `pat` + is compiled as a regex. When `repl` is a string, it replaces matching + regex patterns as with :meth:`re.sub`. NaN value(s) in the Series are + left as is: - >>> pd.Series(['f.o', 'fuz', np.nan]).str.replace('f.', 'ba', regex=False) + >>> pd.Series(['foo', 'fuz', np.nan]).str.replace('f.', 'ba', regex=True) 0 bao - 1 fuz + 1 baz 2 NaN dtype: object - When `pat` is a string and `regex` is True, the given `pat` is compiled - as a regex. When `repl` is a string, it replaces matching regex patterns - as with :meth:`re.sub`: + When `pat` is a string and `regex` is False, every `pat` is replaced with + `repl` as with :meth:`str.replace`: - >>> pd.Series(['foo', 'fuz', np.nan]).str.replace('f.', 'ba', regex=True) + >>> pd.Series(['f.o', 'fuz', np.nan]).str.replace('f.', 'ba', regex=False) 0 bao - 1 baz + 1 fuz 2 NaN dtype: object @@ -414,6 +414,13 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): 1 bar 2 NaN dtype: object + + Raises + ------ + ValueError + * if `regex` is False and `repl` is a callable or `pat` is a compiled + regex + * if `pat` is a compiled regex and `case` or `flags` is set """ # Check whether repl is valid (GH 13438, GH 15055) From 1006e96a8db11202a854b2cb891d30a9237576df Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Tue, 27 Feb 2018 14:22:18 -0600 Subject: [PATCH 10/12] Fixup whitespace --- doc/source/text.rst | 2 +- doc/source/whatsnew/v0.23.0.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/text.rst b/doc/source/text.rst index 047be960cd10e..da8e40892716e 100644 --- a/doc/source/text.rst +++ b/doc/source/text.rst @@ -157,7 +157,7 @@ and ``repl`` must be strings: # These lines are equivalent dollars.str.replace(r'-\$', '-') - dollars.str.replace('-$', '-', regex=False) + dollars.str.replace('-$', '-', regex=False) .. versionadded:: 0.20.0 diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index a166f32ba3e09..7f46365c4f647 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -620,7 +620,7 @@ Other API Changes - Set operations (union, difference...) on :class:`IntervalIndex` with incompatible index types will now raise a ``TypeError`` rather than a ``ValueError`` (:issue:`19329`) - :class:`DateOffset` objects render more simply, e.g. ```` instead of ```` (:issue:`19403`) - ``Categorical.fillna`` now validates its ``value`` and ``method`` keyword arguments. It now raises when both or none are specified, matching the behavior of :meth:`Series.fillna` (:issue:`19682`) -- :func:`Series.str.replace` now takes an optional `regex` keyword which, when set to ``False``, uses literal string replacement rather than regex replacement (:issue:`16808`) +- :func:`Series.str.replace` now takes an optional `regex` keyword which, when set to ``False``, uses literal string replacement rather than regex replacement (:issue:`16808`) .. _whatsnew_0230.deprecations: From 0b34caca945a7c9f02964f976a50b0a5dbdabac2 Mon Sep 17 00:00:00 2001 From: David Krych Date: Tue, 27 Feb 2018 19:36:02 -0500 Subject: [PATCH 11/12] Retrigger travis-ci From f2198b092f7f005571d67bf301dedfc9ffbf04dd Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Wed, 28 Feb 2018 06:12:47 -0500 Subject: [PATCH 12/12] move Raises --- pandas/core/strings.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/pandas/core/strings.py b/pandas/core/strings.py index e1eccb5deffad..91b97c788889b 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -348,6 +348,13 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): ------- replaced : Series/Index of objects + Raises + ------ + ValueError + * if `regex` is False and `repl` is a callable or `pat` is a compiled + regex + * if `pat` is a compiled regex and `case` or `flags` is set + Notes ----- When `pat` is a compiled regex, all flags should be included in the @@ -415,12 +422,6 @@ def str_replace(arr, pat, repl, n=-1, case=None, flags=0, regex=True): 2 NaN dtype: object - Raises - ------ - ValueError - * if `regex` is False and `repl` is a callable or `pat` is a compiled - regex - * if `pat` is a compiled regex and `case` or `flags` is set """ # Check whether repl is valid (GH 13438, GH 15055)