From 12aba35771d635c8dabf1a9e3b8b9ee6d7c7e229 Mon Sep 17 00:00:00 2001 From: discort Date: Wed, 2 Aug 2017 08:19:15 +0300 Subject: [PATCH 1/2] Normalized index type and name of empty series --- doc/source/whatsnew/v0.21.0.txt | 1 + pandas/core/resample.py | 5 +++++ pandas/tests/test_resample.py | 11 +++++++++++ 3 files changed, 17 insertions(+) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index fad6647d4de8d..72175f877532b 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -299,6 +299,7 @@ Groupby/Resample/Rolling - Bug in :func:`infer_freq` causing indices with 2-day gaps during the working week to be wrongly inferred as business daily (:issue:`16624`) - Bug in ``.rolling(...).quantile()`` which incorrectly used different defaults than :func:`Series.quantile()` and :func:`DataFrame.quantile()` (:issue:`9413`, :issue:`16211`) - Bug in ``groupby.transform()`` that would coerce boolean dtypes back to float (:issue:`16875`) +- Bug in ``Series.resample(...).apply()`` where an empty ``Series`` modified the source index and did not return the name of a ``Series`` (:issue:`14313`) Sparse ^^^^^^ diff --git a/pandas/core/resample.py b/pandas/core/resample.py index a8a48624fb885..03a1c531bc0dc 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -778,6 +778,11 @@ def _wrap_result(self, result): # convert if needed if self.kind == 'period' and not isinstance(result.index, PeriodIndex): result.index = result.index.to_period(self.freq) + + if isinstance(result, com.ABCSeries) and result.empty: + obj = self.obj + result.index = obj.index._shallow_copy(freq=to_offset(self.freq)) + result.name = getattr(obj, 'name', None) return result diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py index 08fa7992e8da1..6760b99d0aaa3 100644 --- a/pandas/tests/test_resample.py +++ b/pandas/tests/test_resample.py @@ -2192,6 +2192,17 @@ def test_resample_datetime_values(self): res = df['timestamp'].resample('2D').first() tm.assert_series_equal(res, exp) + def test_apply_to_empty_series(self): + # GH 14313 + series = self.create_series()[:0] + + for freq in ['M', 'D', 'H']: + result = series.resample(freq).apply(lambda x: 1) + expected = series.resample(freq).apply(np.sum) + + assert result.name == expected.name + assert_series_equal(result, expected, check_dtype=False) + class TestPeriodIndex(Base): _index_factory = lambda x: period_range From 3088bcc6038db16f50860ec9735d1cc101bdcadb Mon Sep 17 00:00:00 2001 From: discort Date: Wed, 2 Aug 2017 15:52:19 +0300 Subject: [PATCH 2/2] Improved tests & addressed comments --- pandas/core/resample.py | 12 ++++++------ pandas/tests/test_resample.py | 29 ++++++++++++++++++----------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 03a1c531bc0dc..96e7a6a3b3904 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -17,7 +17,7 @@ from pandas.core.indexes.period import PeriodIndex, period_range import pandas.core.common as com import pandas.core.algorithms as algos -from pandas.core.dtypes.generic import ABCDataFrame +from pandas.core.dtypes.generic import ABCDataFrame, ABCSeries import pandas.compat as compat from pandas.compat.numpy import function as nv @@ -439,6 +439,11 @@ def _wrap_result(self, result): if isinstance(result, com.ABCSeries) and self._selection is not None: result.name = self._selection + if isinstance(result, ABCSeries) and result.empty: + obj = self.obj + result.index = obj.index._shallow_copy(freq=to_offset(self.freq)) + result.name = getattr(obj, 'name', None) + return result def pad(self, limit=None): @@ -778,11 +783,6 @@ def _wrap_result(self, result): # convert if needed if self.kind == 'period' and not isinstance(result.index, PeriodIndex): result.index = result.index.to_period(self.freq) - - if isinstance(result, com.ABCSeries) and result.empty: - obj = self.obj - result.index = obj.index._shallow_copy(freq=to_offset(self.freq)) - result.name = getattr(obj, 'name', None) return result diff --git a/pandas/tests/test_resample.py b/pandas/tests/test_resample.py index 6760b99d0aaa3..d938d5bf9f3ab 100644 --- a/pandas/tests/test_resample.py +++ b/pandas/tests/test_resample.py @@ -852,6 +852,16 @@ def test_resample_loffset_arg_type(self): assert_frame_equal(result_agg, expected) assert_frame_equal(result_how, expected) + def test_apply_to_empty_series(self): + # GH 14313 + series = self.create_series()[:0] + + for freq in ['M', 'D', 'H']: + result = series.resample(freq).apply(lambda x: 1) + expected = series.resample(freq).apply(np.sum) + + assert_series_equal(result, expected, check_dtype=False) + class TestDatetimeIndex(Base): _index_factory = lambda x: date_range @@ -2192,17 +2202,6 @@ def test_resample_datetime_values(self): res = df['timestamp'].resample('2D').first() tm.assert_series_equal(res, exp) - def test_apply_to_empty_series(self): - # GH 14313 - series = self.create_series()[:0] - - for freq in ['M', 'D', 'H']: - result = series.resample(freq).apply(lambda x: 1) - expected = series.resample(freq).apply(np.sum) - - assert result.name == expected.name - assert_series_equal(result, expected, check_dtype=False) - class TestPeriodIndex(Base): _index_factory = lambda x: period_range @@ -2805,6 +2804,14 @@ def test_evenly_divisible_with_no_extra_bins(self): result = df.resample('7D').sum() assert_frame_equal(result, expected) + def test_apply_to_empty_series(self): + # GH 14313 + series = self.create_series()[:0] + + for freq in ['M', 'D', 'H']: + with pytest.raises(TypeError): + series.resample(freq).apply(lambda x: 1) + class TestTimedeltaIndex(Base): _index_factory = lambda x: timedelta_range