diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 00379c7e9d511..51735548db7d3 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -84,6 +84,7 @@ Other Enhancements - :meth:`Series.nlargest`, :meth:`Series.nsmallest`, :meth:`DataFrame.nlargest`, and :meth:`DataFrame.nsmallest` now accept the value ``"all"`` for the ``keep`` argument. This keeps all ties for the nth largest/smallest value (:issue:`16818`) - :class:`IntervalIndex` has gained the :meth:`~IntervalIndex.set_closed` method to change the existing ``closed`` value (:issue:`21670`) - :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) +- :func:`Series.str.zfill()` now matches with standard string library zfill (:issue:`20868`) - .. _whatsnew_0240.api_breaking: diff --git a/pandas/core/strings.py b/pandas/core/strings.py index e4765c00f80fd..29990e0efa8af 100644 --- a/pandas/core/strings.py +++ b/pandas/core/strings.py @@ -2557,20 +2557,26 @@ def zfill(self, width): Note that ``10`` and ``NaN`` are not strings, therefore they are converted to ``NaN``. The minus sign in ``'-1'`` is treated as a - regular character and the zero is added to the left of it + special character and the zero is added to the right of it (:meth:`str.zfill` would have moved it to the left). ``1000`` remains unchanged as it is longer than `width`. >>> s.str.zfill(3) - 0 0-1 + 0 -01 1 001 2 1000 3 NaN 4 NaN dtype: object """ - result = str_pad(self._data, width, side='left', fillchar='0') - return self._wrap_result(result) + + if not is_integer(width): + msg = 'width must be of integer type, not {0}' + raise TypeError(msg.format(type(width).__name__)) + + f = lambda x: x.zfill(width) + + return self._wrap_result(_na_map(f, self._data)) @copy(str_slice) def slice(self, start=None, stop=None, step=None): diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py index 9d008dfd25c90..8624cba57a354 100644 --- a/pandas/tests/test_strings.py +++ b/pandas/tests/test_strings.py @@ -2220,27 +2220,31 @@ def test_center_ljust_rjust_fillchar(self): result = values.str.rjust(5, fillchar=1) def test_zfill(self): - values = Series(['1', '22', 'aaa', '333', '45678']) + values = Series(['1', '+1', '-1', '22', 'aaa', '333', '45678']) result = values.str.zfill(5) - expected = Series(['00001', '00022', '00aaa', '00333', '45678']) + expected = Series(['00001', '+0001', '-0001', '00022', '00aaa', + '00333', '45678']) tm.assert_series_equal(result, expected) expected = np.array([v.zfill(5) for v in values.values], dtype=np.object_) tm.assert_numpy_array_equal(result.values, expected) result = values.str.zfill(3) - expected = Series(['001', '022', 'aaa', '333', '45678']) + expected = Series(['001', '+01', '-01', '022', 'aaa', '333', '45678']) tm.assert_series_equal(result, expected) expected = np.array([v.zfill(3) for v in values.values], dtype=np.object_) tm.assert_numpy_array_equal(result.values, expected) - values = Series(['1', np.nan, 'aaa', np.nan, '45678']) + values = Series(['1', np.nan, 'aaa', np.nan, '45678', 10]) result = values.str.zfill(5) - expected = Series(['00001', np.nan, '00aaa', np.nan, '45678']) + expected = Series(['00001', np.nan, '00aaa', np.nan, '45678', np.nan]) tm.assert_series_equal(result, expected) + with tm.assert_raises_regex(TypeError, "width must be of integer"): + values.str.zfill('5') + def test_split(self): values = Series(['a_b_c', 'c_d_e', NA, 'f_g_h'])