Repository: sunpy/sunpy

Issue:
Add `reindex` method to `GenericTimeseries`
Currently if I want to re-index some data the code is messy. In this case, I am re-indexing `mag_data` on to the timestamps of `swa_data`, both of which are `GenericTimeseries` objects:

```python
mag_df = mag_data.to_dataframe()
mag_reindexed = mag_data.to_dataframe().reindex(swa_data.index,
                                                method='nearest')
mag_reindexed = GenericTimeSeries(mag_reindexed, units=mag_data.units)
```

It would be good to add a `reindex` method to `GenericTimeseries` to wrap this functionality, so instead I could just do:

```python
mag_reindexed = mag_data.reindex(saw_data.index)
```


Discussion:

Resolving patch:
diff --git a/sunpy/timeseries/timeseriesbase.py b/sunpy/timeseries/timeseriesbase.py
--- a/sunpy/timeseries/timeseriesbase.py
+++ b/sunpy/timeseries/timeseriesbase.py
@@ -445,6 +445,41 @@ def concatenate(self, others, same_source=False, **kwargs):
         object._sanitize_units()
         return object
 
+    def reindex(self, index, method="nearest", **kwargs):
+        """
+        Returns a new time series with a new index.
+
+        By default values on the new time series are filled using a
+        nearest valid observation method. See `~pandas.DataFrame.reindex`
+        for the different re-indexing options available.
+
+        Parameters
+        ----------
+        index : `~sunpy.timeseries.TimeSeries` or `~pandas.DatetimeIndex`
+            Another `~sunpy.timeseries.TimeSeries` or a valid index column.
+        method : `str`, optional
+            Method to use for filling holes in reindexed time series.
+            Defaults to "nearest".
+
+        Returns
+        -------
+        `~sunpy.timeseries.TimeSeries`
+            A `~sunpy.timeseries.TimeSeries` with new index.
+
+        Notes
+        -----
+        This method is a wrapper around `pandas.DataFrame.reindex`; all additional
+        keyword arguments are passed to this method.
+        """
+        if isinstance(index, GenericTimeSeries):
+            index = index.index
+        object = GenericTimeSeries(self._data.reindex(index, method=method, **kwargs),
+                                   meta=TimeSeriesMetaData(copy.copy(self.meta.metadata)),
+                                   units=copy.copy(self.units))
+        object._sanitize_metadata()
+        object._sanitize_units()
+        return object
+
 # #### Plotting Methods #### #
 
     def plot(self, axes=None, **plot_args):


Test patch:
diff --git a/sunpy/timeseries/tests/test_timeseriesbase.py b/sunpy/timeseries/tests/test_timeseriesbase.py
--- a/sunpy/timeseries/tests/test_timeseriesbase.py
+++ b/sunpy/timeseries/tests/test_timeseriesbase.py
@@ -906,6 +906,18 @@ def test_ts_sort_index(generic_ts):
     assert generic_ts.sort_index().to_dataframe().equals(generic_ts.to_dataframe().sort_index())
 
 
+def test_ts_reindex(generic_ts):
+    dates = generic_ts.time_range.start + TimeDelta(np.arange(60)*u.minute)
+    new_index = dates.isot.astype('datetime64')
+    # Test for pandas.DatetimeIndex as index
+    generic_ts_reindexed_1 = generic_ts.reindex(new_index, method="nearest")
+    df_selected = generic_ts.to_dataframe().loc[new_index]
+    assert generic_ts_reindexed_1.to_dataframe().equals(df_selected)
+    # Test for sunpy.timeseries.TimeSeries as index
+    generic_ts_reindexed_2 = generic_ts.reindex(generic_ts_reindexed_1, method="nearest")
+    assert generic_ts_reindexed_2.to_dataframe().equals(generic_ts_reindexed_1.to_dataframe())
+
+
 # TODO:
 # _validate_units
 # _validate_meta