From f3e3e1581b171049247aa54a599f16906367a1b0 Mon Sep 17 00:00:00 2001 From: Gregory Livschitz Date: Sat, 9 Apr 2016 00:27:27 -0400 Subject: [PATCH 1/2] BUG 12800 fixed inconsistent behavior of last_valid_index --- pandas/core/frame.py | 6 ++++++ pandas/tests/frame/test_timeseries.py | 5 +++++ pandas/tests/series/test_timeseries.py | 5 +++++ 3 files changed, 16 insertions(+) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 99fa722aebb7b..96a2b87a1bdb7 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -3766,12 +3766,18 @@ def first_valid_index(self): """ Return label for first non-NA/null value """ + if len(self) == 0: + return None + return self.index[self.count(1) > 0][0] def last_valid_index(self): """ Return label for last non-NA/null value """ + if len(self) == 0: + return None + return self.index[self.count(1) > 0][-1] # ---------------------------------------------------------------------- diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index 115e942dceb0f..439d91065e615 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -336,3 +336,8 @@ def test_first_last_valid(self): index = frame.last_valid_index() self.assertEqual(index, frame.index[-6]) + + def test_empty_first_last(self): + empty_frame = DataFrame() + self.assertIsNone(empty_frame.last_valid_index()) + self.assertIsNone(empty_frame.first_valid_index()) \ No newline at end of file diff --git a/pandas/tests/series/test_timeseries.py b/pandas/tests/series/test_timeseries.py index 00b5f01483e29..577eec01bf931 100644 --- a/pandas/tests/series/test_timeseries.py +++ b/pandas/tests/series/test_timeseries.py @@ -617,3 +617,8 @@ def test_timeseries_coercion(self): self.assertTrue(ser.is_time_series) self.assertTrue(ser.index.is_all_dates) self.assertIsInstance(ser.index, DatetimeIndex) + + def test_empty_first_last(self): + empty_frame = Series() + self.assertIsNone(empty_frame.last_valid_index()) + self.assertIsNone(empty_frame.first_valid_index()) \ No newline at end of file From fed9b57fdfb1bd039595b7f09013240a62c0c43a Mon Sep 17 00:00:00 2001 From: Gregory Livschitz Date: Sat, 9 Apr 2016 13:09:51 -0400 Subject: [PATCH 2/2] BUG 12800 added whatsnew note and comments for tests --- doc/source/whatsnew/v0.18.1.txt | 1 + pandas/tests/frame/test_timeseries.py | 1 + pandas/tests/series/test_timeseries.py | 7 ++++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.18.1.txt b/doc/source/whatsnew/v0.18.1.txt index 3e45b2ca37229..857b0cdc3aec6 100644 --- a/doc/source/whatsnew/v0.18.1.txt +++ b/doc/source/whatsnew/v0.18.1.txt @@ -237,3 +237,4 @@ Bug Fixes - Bug in ``.describe()`` resets categorical columns information (:issue:`11558`) - Bug where ``loffset`` argument was not applied when calling ``resample().count()`` on a timeseries (:issue:`12725`) - ``pd.read_excel()`` now accepts path objects (e.g. ``pathlib.Path``, ``py.path.local``) for the file path, in line with other ``read_*`` functions (:issue:`12655`) +- Bug in ``DataFrame`` inconsistent behavior ``last_valid_index()``, ``first_valid_index`` (:issue:`12800`) \ No newline at end of file diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index 439d91065e615..f20f52fb9c07d 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -337,6 +337,7 @@ def test_first_last_valid(self): index = frame.last_valid_index() self.assertEqual(index, frame.index[-6]) + # GH #12800 def test_empty_first_last(self): empty_frame = DataFrame() self.assertIsNone(empty_frame.last_valid_index()) diff --git a/pandas/tests/series/test_timeseries.py b/pandas/tests/series/test_timeseries.py index 577eec01bf931..dec30f97d2e2a 100644 --- a/pandas/tests/series/test_timeseries.py +++ b/pandas/tests/series/test_timeseries.py @@ -19,7 +19,6 @@ class TestSeriesTimeSeries(TestData, tm.TestCase): - _multiprocess_can_split_ = True def test_shift(self): @@ -222,6 +221,7 @@ def test_asof(self): def test_getitem_setitem_datetimeindex(self): from pandas import date_range + N = 50 # testing with timezone, GH #2785 rng = date_range('1/1/1990', periods=N, freq='H', tz='US/Eastern') @@ -304,6 +304,7 @@ def test_getitem_setitem_datetime_tz_pytz(self): from pytz import timezone as tz from pandas import date_range + N = 50 # testing with timezone, GH #2785 rng = date_range('1/1/1990', periods=N, freq='H', tz='US/Eastern') @@ -343,6 +344,7 @@ def test_getitem_setitem_datetime_tz_dateutil(self): x) # handle special case for utc in dateutil from pandas import date_range + N = 50 # testing with timezone, GH #2785 rng = date_range('1/1/1990', periods=N, freq='H', tz='US/Eastern') @@ -372,6 +374,7 @@ def test_getitem_setitem_datetime_tz_dateutil(self): def test_getitem_setitem_periodindex(self): from pandas import period_range + N = 50 rng = period_range('1/1/1990', periods=N, freq='H') ts = Series(np.random.randn(N), index=rng) @@ -460,6 +463,7 @@ def test_asof_periodindex(self): def test_asof_more(self): from pandas import date_range + s = Series([nan, nan, 1, 2, nan, nan, 3, 4, 5], index=date_range('1/1/2000', periods=9)) @@ -618,6 +622,7 @@ def test_timeseries_coercion(self): self.assertTrue(ser.index.is_all_dates) self.assertIsInstance(ser.index, DatetimeIndex) + # GH #12800 def test_empty_first_last(self): empty_frame = Series() self.assertIsNone(empty_frame.last_valid_index())