Skip to content

Commit 9b63034

Browse files
authored
BUG: Series.str.zfill() behaves differently than str.zfill() from standard library (#47633)
* fix GH20868 * fix pre-commit issue * add more tests and describle the differences
1 parent a4fec22 commit 9b63034

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

doc/source/whatsnew/v1.5.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,7 @@ Conversion
861861
Strings
862862
^^^^^^^
863863
- Bug in :meth:`str.startswith` and :meth:`str.endswith` when using other series as parameter _pat_. Now raises ``TypeError`` (:issue:`3485`)
864+
- Bug in :meth:`Series.str.zfill` when strings contain leading signs, padding '0' before the sign character rather than after as ``str.zfill`` from standard library (:issue:`20868`)
864865
-
865866

866867
Interval

pandas/core/strings/accessor.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -1688,19 +1688,23 @@ def zfill(self, width):
16881688
16891689
Note that ``10`` and ``NaN`` are not strings, therefore they are
16901690
converted to ``NaN``. The minus sign in ``'-1'`` is treated as a
1691-
regular character and the zero is added to the left of it
1691+
special character and the zero is added to the right of it
16921692
(:meth:`str.zfill` would have moved it to the left). ``1000``
16931693
remains unchanged as it is longer than `width`.
16941694
16951695
>>> s.str.zfill(3)
1696-
0 0-1
1696+
0 -01
16971697
1 001
16981698
2 1000
16991699
3 NaN
17001700
4 NaN
17011701
dtype: object
17021702
"""
1703-
result = self.pad(width, side="left", fillchar="0")
1703+
if not is_integer(width):
1704+
msg = f"width must be of integer type, not {type(width).__name__}"
1705+
raise TypeError(msg)
1706+
f = lambda x: x.zfill(width)
1707+
result = self._data.array._str_map(f)
17041708
return self._wrap_result(result)
17051709

17061710
def slice(self, start=None, stop=None, step=None):

pandas/tests/strings/test_strings.py

+25
Original file line numberDiff line numberDiff line change
@@ -803,3 +803,28 @@ def test_str_accessor_in_apply_func():
803803
expected = Series(["A/D", "B/E", "C/F"])
804804
result = df.apply(lambda f: "/".join(f.str.upper()), axis=1)
805805
tm.assert_series_equal(result, expected)
806+
807+
808+
def test_zfill():
809+
# https://github.com/pandas-dev/pandas/issues/20868
810+
value = Series(["-1", "1", "1000", 10, np.nan])
811+
expected = Series(["-01", "001", "1000", np.nan, np.nan])
812+
tm.assert_series_equal(value.str.zfill(3), expected)
813+
814+
value = Series(["-2", "+5"])
815+
expected = Series(["-0002", "+0005"])
816+
tm.assert_series_equal(value.str.zfill(5), expected)
817+
818+
819+
def test_zfill_with_non_integer_argument():
820+
value = Series(["-2", "+5"])
821+
wid = "a"
822+
msg = f"width must be of integer type, not {type(wid).__name__}"
823+
with pytest.raises(TypeError, match=msg):
824+
value.str.zfill(wid)
825+
826+
827+
def test_zfill_with_leading_sign():
828+
value = Series(["-cat", "-1", "+dog"])
829+
expected = Series(["-0cat", "-0001", "+0dog"])
830+
tm.assert_series_equal(value.str.zfill(5), expected)

0 commit comments

Comments
 (0)