Repository: pandas-dev/pandas

Issue:
BUG: step argument in the slice StringMethod not working
The `step` argument in the `slice` StringMethods has no effect:

```
In [18]: s = pd.Series(['abcde', 'fghij'])

In [19]: s.str.slice?
Definition:  s.str.slice(self, start=None, stop=None, step=1)
Slice substrings from each element in array

Parameters
----------
start : int or None
stop : int or None

Returns
-------
sliced : array

In [22]: s.str.slice(step=1)
Out[22]: 
0    abcde
1    fghij
dtype: object

In [23]: s.str.slice(step=2)
Out[23]: 
0    abcde
1    fghij
dtype: object

In [24]: s[0][::2]
Out[24]: 'ace'
```



Discussion:

Resolving patch:
diff --git a/pandas/core/strings.py b/pandas/core/strings.py
--- a/pandas/core/strings.py
+++ b/pandas/core/strings.py
@@ -666,7 +666,7 @@ def str_split(arr, pat=None, n=None, return_type='series'):
     return res
 
 
-def str_slice(arr, start=None, stop=None, step=1):
+def str_slice(arr, start=None, stop=None, step=None):
     """
     Slice substrings from each element in array
 
@@ -674,6 +674,7 @@ def str_slice(arr, start=None, stop=None, step=1):
     ----------
     start : int or None
     stop : int or None
+    step : int or None
 
     Returns
     -------
@@ -993,8 +994,8 @@ def center(self, width):
         return self._wrap_result(result)
 
     @copy(str_slice)
-    def slice(self, start=None, stop=None, step=1):
-        result = str_slice(self.series, start, stop)
+    def slice(self, start=None, stop=None, step=None):
+        result = str_slice(self.series, start, stop, step)
         return self._wrap_result(result)
 
     @copy(str_slice)


Test patch:
diff --git a/pandas/tests/test_strings.py b/pandas/tests/test_strings.py
--- a/pandas/tests/test_strings.py
+++ b/pandas/tests/test_strings.py
@@ -628,6 +628,7 @@ def test_empty_str_methods(self):
         tm.assert_series_equal(empty_str, empty.str.center(42))
         tm.assert_series_equal(empty_list, empty.str.split('a'))
         tm.assert_series_equal(empty_str, empty.str.slice(stop=1))
+        tm.assert_series_equal(empty_str, empty.str.slice(step=1))
         tm.assert_series_equal(empty_str, empty.str.strip())
         tm.assert_series_equal(empty_str, empty.str.lstrip())
         tm.assert_series_equal(empty_str, empty.str.rstrip())
@@ -922,6 +923,17 @@ def test_slice(self):
         exp = Series(['foo', 'bar', NA, 'baz'])
         tm.assert_series_equal(result, exp)
 
+        for start, stop, step in [(0, 3, -1), (None, None, -1),
+                                  (3, 10, 2), (3, 0, -1)]:
+            try:
+                result = values.str.slice(start, stop, step)
+                expected = Series([s[start:stop:step] if not isnull(s) else NA for s in
+                                   values])
+                tm.assert_series_equal(result, expected)
+            except:
+                print('failed on %s:%s:%s' % (start, stop, step))
+                raise
+
         # mixed
         mixed = Series(['aafootwo', NA, 'aabartwo', True, datetime.today(),
                         None, 1, 2.])
@@ -933,6 +945,10 @@ def test_slice(self):
         tm.assert_isinstance(rs, Series)
         tm.assert_almost_equal(rs, xp)
 
+        rs = Series(mixed).str.slice(2, 5, -1)
+        xp = Series(['oof', NA, 'rab', NA, NA,
+                     NA, NA, NA])
+
         # unicode
         values = Series([u('aafootwo'), u('aabartwo'), NA,
                          u('aabazqux')])
@@ -941,6 +957,10 @@ def test_slice(self):
         exp = Series([u('foo'), u('bar'), NA, u('baz')])
         tm.assert_series_equal(result, exp)
 
+        result = values.str.slice(0, -1, 2)
+        exp = Series([u('afow'), u('abrw'), NA, u('abzu')])
+        tm.assert_series_equal(result, exp)
+
     def test_slice_replace(self):
         pass
 
@@ -1151,6 +1171,10 @@ def test_string_slice_get_syntax(self):
         expected = s.str.slice(stop=3)
         assert_series_equal(result, expected)
 
+        result = s.str[2::-1]
+        expected = s.str.slice(start=2, step=-1)
+        assert_series_equal(result, expected)
+
     def test_string_slice_out_of_bounds(self):
         s = Series([(1, 2), (1,), (3,4,5)])