Repository: pandas-dev/pandas

Issue:
BUG: reindex() and reindex_like() fill behavior is different in pandas 12.0 and 13.1?
I just came across an issue which caused me serious troubles since upgrading from pandas 12.0 to 13.1. It happens when using a fill method with a reindex() or reindex_like() method. Moreover, those method are not giving consistent results anymore! I have not tested how this issue or originates from changed .ffill() and similar method, but I see it propagates to resample(). Could not find any recent mentioning of the strange behavior and no hints in the docs or What's New section. 

This is the problem I encounter using pandas 12.0 (with numpy 1.7.1, in both, 32bit Python 2.7.5 Python x,y and 64bit, WinPython-64bit-2.7.4.1; windows 7) and pandas 13.1 (D:\PortableApps\WinPython-64bit-2.7.6.2, numpy 1.8.0). Pandas 12.0 behavior is the same for the 32 bit and 64 bit versions, so this cannot explain the problem.

Code:

```
import pandas as pd
# Make low frequency timeseries:
i30 = index=pd.date_range('2002-02-02', periods=4, freq='30T')
s=pd.Series(np.arange(4.), index=i30)
s[2] = np.NaN 

# Upsample by factor 3 with reindex() and resample() methods:
i10 = pd.date_range(i30[0], i30[-1], freq='10T')
s10 = s.reindex(index=i10, method='bfill')
s10_2 = s.reindex(index=i10, method='bfill', limit=2)
r10 = s.resample('10Min', fill_method='bfill')
r10_2 = s.resample('10Min', fill_method='bfill', limit=2)
```

In pandas 12.0: s10 equals s10_2 equals r10 equals r10_2

```
s10
Out[60]: 
2002-02-02 00:00:00     0
2002-02-02 00:10:00     1
2002-02-02 00:20:00     1
2002-02-02 00:30:00     1
2002-02-02 00:40:00   NaN
2002-02-02 00:50:00   NaN
2002-02-02 01:00:00   NaN
2002-02-02 01:10:00     3
2002-02-02 01:20:00     3
2002-02-02 01:30:00     3
Freq: 10T, dtype: float64
```

In pandas 13.1: s10 does not equal s10_2; s10 has all NaN's filled

```
s10
Out[120]: 
2002-02-02 00:00:00    0
2002-02-02 00:10:00    1
2002-02-02 00:20:00    1
2002-02-02 00:30:00    1
2002-02-02 00:40:00    3
2002-02-02 00:50:00    3
2002-02-02 01:00:00    3
2002-02-02 01:10:00    3
2002-02-02 01:20:00    3
2002-02-02 01:30:00    3
Freq: 10T, dtype: float64
```

Same holds for resampled series r10
Conclusion: in pandas 13.1, all is filled if limit=None which breaks with the pandas 12.0 behavior. I think the 12.0 behavior is mre sensible; only fill the gaps created from upsampling. 
This even more import for the reindex_like method because there the "limit" key cannot limit which gaps are filled in pandas 13.1:

```
s.reindex_like(s10, method='bfill', limit=2)
Out[121]: 
2002-02-02 00:00:00    0
2002-02-02 00:10:00    1
2002-02-02 00:20:00    1
2002-02-02 00:30:00    1
2002-02-02 00:40:00    3
2002-02-02 00:50:00    3
2002-02-02 01:00:00    3
2002-02-02 01:10:00    3
2002-02-02 01:20:00    3
2002-02-02 01:30:00    3
Freq: 10T, dtype: float64
```

Hope this is clear and I can be reproduced? I hope this can be fixed soon. But of course, if you can reproduce this behavior and it has indeed change from 12.0 to 13.1, this should be in the docs



Discussion:
the `reindex_like` wasn't passing the `limit` keyword thru to reindex so that is already fixed...will have to look at the rest


Resolving patch:
diff --git a/pandas/core/generic.py b/pandas/core/generic.py
--- a/pandas/core/generic.py
+++ b/pandas/core/generic.py
@@ -1589,23 +1589,9 @@ def _reindex_axes(self, axes, level, limit, method, fill_value, copy,
 
             axis = self._get_axis_number(a)
             ax = self._get_axis(a)
-            try:
-                new_index, indexer = ax.reindex(
-                    labels, level=level, limit=limit, method=method,
-                    takeable=takeable)
-            except (ValueError):
-
-                # catch trying to reindex a non-monotonic index with a
-                # specialized indexer e.g. pad, so fallback to the regular
-                # indexer this will show up on reindexing a not-naturally
-                # ordering series,
-                # e.g.
-                # Series(
-                #     [1,2,3,4], index=['a','b','c','d']
-                # ).reindex(['c','b','g'], method='pad')
-                new_index, indexer = ax.reindex(
-                    labels, level=level, limit=limit, method=None,
-                    takeable=takeable)
+            new_index, indexer = ax.reindex(
+                labels, level=level, limit=limit, method=method,
+                takeable=takeable)
 
             obj = obj._reindex_with_indexers(
                 {axis: [new_index, indexer]}, method=method,
diff --git a/pandas/core/internals.py b/pandas/core/internals.py
--- a/pandas/core/internals.py
+++ b/pandas/core/internals.py
@@ -265,7 +265,7 @@ def reindex_items_from(self, new_ref_items, indexer=None, method=None,
             new_ref_items, indexer = self.items.reindex(new_ref_items,
                                                         limit=limit)
 
-        needs_fill = method is not None and limit is None
+        needs_fill = method is not None
         if fill_value is None:
             fill_value = self.fill_value
 
@@ -275,10 +275,13 @@ def reindex_items_from(self, new_ref_items, indexer=None, method=None,
 
         else:
 
-            # single block reindex
+            # single block reindex, filling is already happending
             if self.ndim == 1:
                 new_values = com.take_1d(self.values, indexer,
                                          fill_value=fill_value)
+                block = make_block(new_values, new_items, new_ref_items,
+                                   ndim=self.ndim, fastpath=True)
+                return block
             else:
 
                 masked_idx = indexer[indexer != -1]
@@ -3705,8 +3708,6 @@ def _reindex_indexer_items(self, new_items, indexer, fill_value):
 
     def reindex_axis0_with_method(self, new_axis, indexer=None, method=None,
                                   fill_value=None, limit=None, copy=True):
-        if method is None:
-            indexer = None
         return self.reindex(new_axis, indexer=indexer, method=method,
                             fill_value=fill_value, limit=limit, copy=copy)
 


Test patch:
diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py
--- a/pandas/tests/test_series.py
+++ b/pandas/tests/test_series.py
@@ -4999,9 +4999,8 @@ def test_reindex_pad(self):
         result = s.reindex(new_index).ffill(downcast='infer')
         assert_series_equal(result, expected)
 
-        # this preserves dtype
-        result = s.reindex(new_index, method='ffill')
-        assert_series_equal(result, expected)
+        # invalid because we can't forward fill on this type of index
+        self.assertRaises(ValueError, lambda : s.reindex(new_index, method='ffill'))
 
         # inferrence of new dtype
         s = Series([True,False,False,True],index=list('abcd'))
diff --git a/pandas/tseries/tests/test_resample.py b/pandas/tseries/tests/test_resample.py
--- a/pandas/tseries/tests/test_resample.py
+++ b/pandas/tseries/tests/test_resample.py
@@ -650,6 +650,28 @@ def test_resample_unequal_times(self):
         # it works!
         df.resample('AS', 'sum')
 
+    def test_resample_consistency(self):
+
+        # GH 6418
+        # resample with bfill / limit / reindex consistency
+
+        i30 = index=pd.date_range('2002-02-02', periods=4, freq='30T')
+        s=pd.Series(np.arange(4.), index=i30)
+        s[2] = np.NaN
+
+        # Upsample by factor 3 with reindex() and resample() methods:
+        i10 = pd.date_range(i30[0], i30[-1], freq='10T')
+
+        s10 = s.reindex(index=i10, method='bfill')
+        s10_2 = s.reindex(index=i10, method='bfill', limit=2)
+        rl = s.reindex_like(s10, method='bfill', limit=2)
+        r10_2 = s.resample('10Min', fill_method='bfill', limit=2)
+        r10 = s.resample('10Min', fill_method='bfill')
+
+        # s10_2, r10, r10_2, rl should all be equal
+        assert_series_equal(s10_2, r10)
+        assert_series_equal(s10_2, r10_2)
+        assert_series_equal(s10_2, rl)
 
 def _simple_ts(start, end, freq='D'):
     rng = date_range(start, end, freq=freq)