From dd22e27b9b6580884eebf9f977a4314241b78b7d Mon Sep 17 00:00:00 2001 From: Elle Hanson Date: Sun, 17 Nov 2019 16:27:07 -0500 Subject: [PATCH] Bug fix GH 29624: calling str.isalpha on empty series returns object dtype, not bool Added dtype=bool argument to make _noarg_wrapper() return a bool Series --- doc/source/whatsnew/v1.0.0.rst | 2 +- pandas/core/strings.py | 10 ++++++++++ pandas/tests/test_strings.py | 19 ++++++++++--------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index c91ced1014dd1..58d1fef9ef5bf 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -354,7 +354,7 @@ Conversion Strings ^^^^^^^ -- +- Calling :meth:`Series.str.isalnum` (and other "ismethods") on an empty Series would return an object dtype instead of bool (:issue:`29624`) - diff --git a/pandas/core/strings.py b/pandas/core/strings.py index a6e0c12526d8a..55ce44d736864 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -3401,59 +3401,69 @@ def rindex(self, sub, start=0, end=None): _doc_args["istitle"] = dict(type="titlecase", method="istitle") _doc_args["isnumeric"] = dict(type="numeric", method="isnumeric") _doc_args["isdecimal"] = dict(type="decimal", method="isdecimal") + # force _noarg_wrapper return type with dtype=bool (GH 29624) isalnum = _noarg_wrapper( lambda x: x.isalnum(), name="isalnum", docstring=_shared_docs["ismethods"] % _doc_args["isalnum"], returns_string=False, + dtype=bool, ) isalpha = _noarg_wrapper( lambda x: x.isalpha(), name="isalpha", docstring=_shared_docs["ismethods"] % _doc_args["isalpha"], returns_string=False, + dtype=bool, ) isdigit = _noarg_wrapper( lambda x: x.isdigit(), name="isdigit", docstring=_shared_docs["ismethods"] % _doc_args["isdigit"], returns_string=False, + dtype=bool, ) isspace = _noarg_wrapper( lambda x: x.isspace(), name="isspace", docstring=_shared_docs["ismethods"] % _doc_args["isspace"], returns_string=False, + dtype=bool, ) islower = _noarg_wrapper( lambda x: x.islower(), name="islower", docstring=_shared_docs["ismethods"] % _doc_args["islower"], returns_string=False, + dtype=bool, ) isupper = _noarg_wrapper( lambda x: x.isupper(), name="isupper", docstring=_shared_docs["ismethods"] % _doc_args["isupper"], returns_string=False, + dtype=bool, ) istitle = _noarg_wrapper( lambda x: x.istitle(), name="istitle", docstring=_shared_docs["ismethods"] % _doc_args["istitle"], returns_string=False, + dtype=bool, ) isnumeric = _noarg_wrapper( lambda x: x.isnumeric(), name="isnumeric", docstring=_shared_docs["ismethods"] % _doc_args["isnumeric"], returns_string=False, + dtype=bool, ) isdecimal = _noarg_wrapper( lambda x: x.isdecimal(), name="isdecimal", docstring=_shared_docs["ismethods"] % _doc_args["isdecimal"], returns_string=False, + dtype=bool, ) @classmethod diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index f5d28ec82d1d4..f68541b620efa 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -1853,15 +1853,16 @@ def test_empty_str_methods(self): tm.assert_series_equal(empty_str, empty.str.get(0)) tm.assert_series_equal(empty_str, empty_bytes.str.decode("ascii")) tm.assert_series_equal(empty_bytes, empty.str.encode("ascii")) - tm.assert_series_equal(empty_str, empty.str.isalnum()) - tm.assert_series_equal(empty_str, empty.str.isalpha()) - tm.assert_series_equal(empty_str, empty.str.isdigit()) - tm.assert_series_equal(empty_str, empty.str.isspace()) - tm.assert_series_equal(empty_str, empty.str.islower()) - tm.assert_series_equal(empty_str, empty.str.isupper()) - tm.assert_series_equal(empty_str, empty.str.istitle()) - tm.assert_series_equal(empty_str, empty.str.isnumeric()) - tm.assert_series_equal(empty_str, empty.str.isdecimal()) + # ismethods should always return boolean (GH 29624) + tm.assert_series_equal(empty_bool, empty.str.isalnum()) + tm.assert_series_equal(empty_bool, empty.str.isalpha()) + tm.assert_series_equal(empty_bool, empty.str.isdigit()) + tm.assert_series_equal(empty_bool, empty.str.isspace()) + tm.assert_series_equal(empty_bool, empty.str.islower()) + tm.assert_series_equal(empty_bool, empty.str.isupper()) + tm.assert_series_equal(empty_bool, empty.str.istitle()) + tm.assert_series_equal(empty_bool, empty.str.isnumeric()) + tm.assert_series_equal(empty_bool, empty.str.isdecimal()) tm.assert_series_equal(empty_str, empty.str.capitalize()) tm.assert_series_equal(empty_str, empty.str.swapcase()) tm.assert_series_equal(empty_str, empty.str.normalize("NFC"))