Skip to content

Commit aa3aaa5

Browse files
committed
ENH: Implement Series.StringMethod.slice_replace
1 parent b62754d commit aa3aaa5

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

doc/source/whatsnew/v0.16.0.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ Enhancements
6262

6363
- Paths beginning with ~ will now be expanded to begin with the user's home directory (:issue:`9066`)
6464
- Added time interval selection in get_data_yahoo (:issue:`9071`)
65+
- Added ``Series.str.slice_replace()``, which previously raised NotImplementedError (:issue:`8888`)
66+
6567

6668
Performance
6769
~~~~~~~~~~~

pandas/core/strings.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -687,15 +687,34 @@ def str_slice(arr, start=None, stop=None, step=None):
687687

688688
def str_slice_replace(arr, start=None, stop=None, repl=None):
689689
"""
690+
Replace a slice of each string with another string.
690691
691692
Parameters
692693
----------
694+
start : int or None
695+
stop : int or None
696+
repl : str or None
693697
694698
Returns
695699
-------
696700
replaced : array
697701
"""
698-
raise NotImplementedError
702+
if repl is None:
703+
repl = ''
704+
705+
def f(x):
706+
if x[start:stop] == '':
707+
local_stop = start
708+
else:
709+
local_stop = stop
710+
y = ''
711+
if start is not None:
712+
y += x[:start]
713+
y += repl
714+
if stop is not None:
715+
y += x[local_stop:]
716+
return y
717+
return _na_map(f, arr)
699718

700719

701720
def str_strip(arr, to_strip=None):
@@ -998,9 +1017,10 @@ def slice(self, start=None, stop=None, step=None):
9981017
result = str_slice(self.series, start, stop, step)
9991018
return self._wrap_result(result)
10001019

1001-
@copy(str_slice)
1002-
def slice_replace(self, i=None, j=None):
1003-
raise NotImplementedError
1020+
@copy(str_slice_replace)
1021+
def slice_replace(self, start=None, stop=None, repl=None):
1022+
result = str_slice_replace(self.series, start, stop, repl)
1023+
return self._wrap_result(result)
10041024

10051025
@copy(str_decode)
10061026
def decode(self, encoding, errors="strict"):

pandas/tests/test_strings.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,39 @@ def test_slice(self):
963963
tm.assert_series_equal(result, exp)
964964

965965
def test_slice_replace(self):
966-
pass
966+
values = Series(['short', 'a bit longer', 'evenlongerthanthat', '', NA])
967+
968+
exp = Series(['shrt', 'a it longer', 'evnlongerthanthat', '', NA])
969+
result = values.str.slice_replace(2, 3)
970+
tm.assert_series_equal(result, exp)
971+
972+
exp = Series(['shzrt', 'a zit longer', 'evznlongerthanthat', 'z', NA])
973+
result = values.str.slice_replace(2, 3, 'z')
974+
tm.assert_series_equal(result, exp)
975+
976+
exp = Series(['shzort', 'a zbit longer', 'evzenlongerthanthat', 'z', NA])
977+
result = values.str.slice_replace(2, 2, 'z')
978+
tm.assert_series_equal(result, exp)
979+
980+
exp = Series(['shzort', 'a zbit longer', 'evzenlongerthanthat', 'z', NA])
981+
result = values.str.slice_replace(2, 1, 'z')
982+
tm.assert_series_equal(result, exp)
983+
984+
exp = Series(['shorz', 'a bit longez', 'evenlongerthanthaz', 'z', NA])
985+
result = values.str.slice_replace(-1, None, 'z')
986+
tm.assert_series_equal(result, exp)
987+
988+
exp = Series(['zrt', 'zer', 'zat', 'z', NA])
989+
result = values.str.slice_replace(None, -2, 'z')
990+
tm.assert_series_equal(result, exp)
991+
992+
exp = Series(['shortz', 'a bit znger', 'evenlozerthanthat', 'z', NA])
993+
result = values.str.slice_replace(6, 8, 'z')
994+
tm.assert_series_equal(result, exp)
995+
996+
exp = Series(['zrt', 'a zit longer', 'evenlongzerthanthat', 'z', NA])
997+
result = values.str.slice_replace(-10, 3, 'z')
998+
tm.assert_series_equal(result, exp)
967999

9681000
def test_strip_lstrip_rstrip(self):
9691001
values = Series([' aa ', ' bb \n', NA, 'cc '])

0 commit comments

Comments
 (0)