Repository: pandas-dev/pandas

Issue:
Resample nearest
pandas supports "pad" (forward fill) and "backfill" upsampling, but not "nearest" upsampling. This could be a nice feature to have, and should be pretty easy, too, as the underlying `Index.get_indexer` method already supports `method='nearest'`.

Possibly this would be as easy as adding only a few lines to the `Resampler` class in `pandas/core/resample.py`. Just monkey-patching this one-liner method seems to work:
```
In [47]: def nearest(self, limit=None):
    ...:     return self._upsample('nearest', limit=limit)
    ...:

In [48]: pd.core.resample.Resampler.nearest = nearest

In [49]: index = pd.date_range('1/1/2000', periods=9, freq='T')
    ...:

In [50]: series = pd.Series(range(9), index=index)

In [51]: series.resample('20s').nearest()[:5]
Out[51]:
2000-01-01 00:00:00    0
2000-01-01 00:00:20    0
2000-01-01 00:00:40    1
2000-01-01 00:01:00    1
2000-01-01 00:01:20    1
Freq: 20S, dtype: int64
```

Obviously this needs tests and documentation. Potetially this could be a good project for a new contributor.

This came up in https://github.com/pydata/xarray/pull/1272 where we are copying the new pandas `resample()` API to xarray.


Discussion:

Resolving patch:
diff --git a/pandas/core/resample.py b/pandas/core/resample.py
--- a/pandas/core/resample.py
+++ b/pandas/core/resample.py
@@ -455,6 +455,10 @@ def pad(self, limit=None):
         limit : integer, optional
             limit of how many values to fill
 
+        Returns
+        -------
+        an upsampled Series
+
         See Also
         --------
         Series.fillna
@@ -463,6 +467,28 @@ def pad(self, limit=None):
         return self._upsample('pad', limit=limit)
     ffill = pad
 
+    def nearest(self, limit=None):
+        """
+        Fill values with nearest neighbor starting from center
+
+        Parameters
+        ----------
+        limit : integer, optional
+            limit of how many values to fill
+
+            .. versionadded:: 0.21.0
+
+        Returns
+        -------
+        an upsampled Series
+
+        See Also
+        --------
+        Series.fillna
+        DataFrame.fillna
+        """
+        return self._upsample('nearest', limit=limit)
+
     def backfill(self, limit=None):
         """
         Backward fill the values
@@ -472,6 +498,10 @@ def backfill(self, limit=None):
         limit : integer, optional
             limit of how many values to fill
 
+        Returns
+        -------
+        an upsampled Series
+
         See Also
         --------
         Series.fillna


Test patch:
diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py
--- a/pandas/tests/test_resample.py
+++ b/pandas/tests/test_resample.py
@@ -1329,6 +1329,14 @@ def test_upsample_with_limit(self):
         expected = ts.reindex(result.index, method='ffill', limit=2)
         assert_series_equal(result, expected)
 
+    def test_nearest_upsample_with_limit(self):
+        rng = date_range('1/1/2000', periods=3, freq='5t')
+        ts = Series(np.random.randn(len(rng)), rng)
+
+        result = ts.resample('t').nearest(limit=2)
+        expected = ts.reindex(result.index, method='nearest', limit=2)
+        assert_series_equal(result, expected)
+
     def test_resample_ohlc(self):
         s = self.series
 
@@ -2934,6 +2942,24 @@ def test_getitem_multiple(self):
         result = r['buyer'].count()
         assert_series_equal(result, expected)
 
+    def test_nearest(self):
+
+        # GH 17496
+        # Resample nearest
+        index = pd.date_range('1/1/2000', periods=3, freq='T')
+        result = pd.Series(range(3), index=index).resample('20s').nearest()
+
+        expected = pd.Series(
+            np.array([0, 0, 1, 1, 1, 2, 2]),
+            index=pd.DatetimeIndex(
+                ['2000-01-01 00:00:00', '2000-01-01 00:00:20',
+                 '2000-01-01 00:00:40', '2000-01-01 00:01:00',
+                 '2000-01-01 00:01:20', '2000-01-01 00:01:40',
+                 '2000-01-01 00:02:00'],
+                dtype='datetime64[ns]',
+                freq='20S'))
+        assert_series_equal(result, expected)
+
     def test_methods(self):
         g = self.frame.groupby('A')
         r = g.resample('2s')
@@ -2960,7 +2986,7 @@ def test_methods(self):
             expected = g.B.apply(lambda x: getattr(x.resample('2s'), f)())
             assert_series_equal(result, expected)
 
-        for f in ['backfill', 'ffill', 'asfreq']:
+        for f in ['nearest', 'backfill', 'ffill', 'asfreq']:
             result = getattr(r, f)()
             expected = g.apply(lambda x: getattr(x.resample('2s'), f)())
             assert_frame_equal(result, expected)