From 7e461a18d9f6928132afec6f48ce968b3e989ba6 Mon Sep 17 00:00:00 2001 From: Kaiqi Dong Date: Mon, 3 Dec 2018 17:43:52 +0100 Subject: [PATCH 1/8] remove \n from docstring --- pandas/core/arrays/datetimes.py | 26 +++++++++++++------------- pandas/core/arrays/timedeltas.py | 16 ++++++++-------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index cfe3afcf3730a..b3df505d56d78 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -82,7 +82,7 @@ def f(self): return result f.__name__ = name - f.__doc__ = docstring + f.__doc__ = "\n{}\n".format(docstring) return property(f) @@ -1072,19 +1072,19 @@ def date(self): return tslib.ints_to_pydatetime(timestamps, box="date") - year = _field_accessor('year', 'Y', "\n The year of the datetime\n") + year = _field_accessor('year', 'Y', "The year of the datetime") month = _field_accessor('month', 'M', - "\n The month as January=1, December=12 \n") - day = _field_accessor('day', 'D', "\nThe days of the datetime\n") - hour = _field_accessor('hour', 'h', "\nThe hours of the datetime\n") - minute = _field_accessor('minute', 'm', "\nThe minutes of the datetime\n") - second = _field_accessor('second', 's', "\nThe seconds of the datetime\n") + "The month as January=1, December=12") + day = _field_accessor('day', 'D', "The days of the datetime") + hour = _field_accessor('hour', 'h', "The hours of the datetime") + minute = _field_accessor('minute', 'm', "The minutes of the datetime") + second = _field_accessor('second', 's', "The seconds of the datetime") microsecond = _field_accessor('microsecond', 'us', - "\nThe microseconds of the datetime\n") + "The microseconds of the datetime") nanosecond = _field_accessor('nanosecond', 'ns', - "\nThe nanoseconds of the datetime\n") + "The nanoseconds of the datetime") weekofyear = _field_accessor('weekofyear', 'woy', - "\nThe week ordinal of the year\n") + "The week ordinal of the year") week = weekofyear _dayofweek_doc = """ The day of the week with Monday=0, Sunday=6. @@ -1129,12 +1129,12 @@ def date(self): "The name of day in a week (ex: Friday)\n\n.. deprecated:: 0.23.0") dayofyear = _field_accessor('dayofyear', 'doy', - "\nThe ordinal day of the year\n") - quarter = _field_accessor('quarter', 'q', "\nThe quarter of the date\n") + "The ordinal day of the year") + quarter = _field_accessor('quarter', 'q', "The quarter of the date") days_in_month = _field_accessor( 'days_in_month', 'dim', - "\nThe number of days in the month\n") + "The number of days in the month") daysinmonth = days_in_month _is_month_doc = """ Indicates whether the date is the {first_or_last} day of the month. diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 830283d31a929..4afc9f5483c2a 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -59,7 +59,7 @@ def f(self): return result f.__name__ = name - f.__doc__ = docstring + f.__doc__ = "\n{}\n".format(docstring) return property(f) @@ -684,16 +684,16 @@ def to_pytimedelta(self): return tslibs.ints_to_pytimedelta(self.asi8) days = _field_accessor("days", "days", - "\nNumber of days for each element.\n") + "Number of days for each element.") seconds = _field_accessor("seconds", "seconds", - "\nNumber of seconds (>= 0 and less than 1 day) " - "for each element.\n") + "Number of seconds (>= 0 and less than 1 day) " + "for each element.") microseconds = _field_accessor("microseconds", "microseconds", - "\nNumber of microseconds (>= 0 and less " - "than 1 second) for each element.\n") + "Number of microseconds (>= 0 and less " + "than 1 second) for each element.") nanoseconds = _field_accessor("nanoseconds", "nanoseconds", - "\nNumber of nanoseconds (>= 0 and less " - "than 1 microsecond) for each element.\n") + "Number of nanoseconds (>= 0 and less " + "than 1 microsecond) for each element.") @property def components(self): From 902e3b690ad940e065aebc2913af9821f32608bc Mon Sep 17 00:00:00 2001 From: Kaiqi Date: Sun, 29 Sep 2019 18:37:38 +0200 Subject: [PATCH 2/8] Fix limit not forwarded in range --- doc/source/whatsnew/v0.25.2.rst | 2 +- pandas/core/indexes/range.py | 11 +++++++++-- pandas/tests/indexes/test_range.py | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v0.25.2.rst b/doc/source/whatsnew/v0.25.2.rst index 14682b706f924..dd71f6114af1c 100644 --- a/doc/source/whatsnew/v0.25.2.rst +++ b/doc/source/whatsnew/v0.25.2.rst @@ -49,7 +49,7 @@ Interval Indexing ^^^^^^^^ -- +- :meth: `DataFrame.reindex` not following limit (:issue:`28631`). - - diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index 8783351cc74d1..7560674bc0019 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -380,8 +380,15 @@ def get_loc(self, key, method=None, tolerance=None): @Appender(_index_shared_docs["get_indexer"]) def get_indexer(self, target, method=None, limit=None, tolerance=None): - if not (method is None and tolerance is None and is_list_like(target)): - return super().get_indexer(target, method=method, tolerance=tolerance) + if not ( + method is None + and tolerance is None + and limit is None + and is_list_like(target) + ): + return super().get_indexer( + target, method=method, tolerance=tolerance, limit=limit + ) if self.step > 0: start, stop, step = self.start, self.stop, self.step diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index 58b98297f00f3..ed183a4dc53ec 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -1037,3 +1037,25 @@ def test_engineless_lookup(self): assert idx.get_loc("a") == -1 assert "_engine" in idx._cache + + def test_limit(self): + # GH 28631 + data = [["A", "A", "A"], ["B", "B", "B"], ["C", "C", "C"], ["D", "D", "D"]] + exp_data = [ + ["A", "A", "A"], + ["B", "B", "B"], + ["C", "C", "C"], + ["D", "D", "D"], + ["D", "D", "D"], + [np.nan, np.nan, np.nan], + ] + df = pd.DataFrame(data) + result = df.reindex([0, 1, 2, 3, 4, 5], method="ffill", limit=1) + expected = pd.DataFrame(exp_data) + tm.assert_frame_equal(result, expected) + + idx = pd.Index(range(4)) + target = pd.Index([0, 1, 2, 3, 4, 5]) + arr = idx.get_indexer(target, method="pad", limit=1) + expected_arr = np.array([0, 1, 2, 3, 3, -1]) + tm.assert_numpy_array_equal(arr, expected_arr) From f34f5542f0ce281cab8821e929069ee86c61dd3b Mon Sep 17 00:00:00 2001 From: Kaiqi Date: Sun, 29 Sep 2019 20:37:28 +0200 Subject: [PATCH 3/8] fix test --- pandas/tests/indexes/test_range.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index ed183a4dc53ec..c0f5492703e2a 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -1058,4 +1058,4 @@ def test_limit(self): target = pd.Index([0, 1, 2, 3, 4, 5]) arr = idx.get_indexer(target, method="pad", limit=1) expected_arr = np.array([0, 1, 2, 3, 3, -1]) - tm.assert_numpy_array_equal(arr, expected_arr) + assert (arr == expected_arr).all() From e78e13ba5577d4bb5918b095a7e93af33ac8195a Mon Sep 17 00:00:00 2001 From: Kaiqi Date: Sun, 29 Sep 2019 22:11:22 +0200 Subject: [PATCH 4/8] code change on Simon review --- doc/source/whatsnew/v0.25.2.rst | 2 +- pandas/tests/indexes/test_range.py | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/source/whatsnew/v0.25.2.rst b/doc/source/whatsnew/v0.25.2.rst index dd71f6114af1c..f904d69d6421b 100644 --- a/doc/source/whatsnew/v0.25.2.rst +++ b/doc/source/whatsnew/v0.25.2.rst @@ -49,7 +49,7 @@ Interval Indexing ^^^^^^^^ -- :meth: `DataFrame.reindex` not following limit (:issue:`28631`). +- Fix regression in :meth:`DataFrame.reindex` not following ``limit`` argument (:issue:`28631`). - - diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index c0f5492703e2a..d05ba64965fd0 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -1038,7 +1038,7 @@ def test_engineless_lookup(self): assert "_engine" in idx._cache - def test_limit(self): + def test_reindex_limit(self): # GH 28631 data = [["A", "A", "A"], ["B", "B", "B"], ["C", "C", "C"], ["D", "D", "D"]] exp_data = [ @@ -1054,8 +1054,10 @@ def test_limit(self): expected = pd.DataFrame(exp_data) tm.assert_frame_equal(result, expected) - idx = pd.Index(range(4)) - target = pd.Index([0, 1, 2, 3, 4, 5]) - arr = idx.get_indexer(target, method="pad", limit=1) - expected_arr = np.array([0, 1, 2, 3, 3, -1]) - assert (arr == expected_arr).all() + def test_get_indexer_limit(self): + # GH 28631 + idx = Index(range(4)) + target = Index([0, 1, 2, 3, 4, 5]) + result = idx.get_indexer(target, method="pad", limit=1) + expected = np.array([0, 1, 2, 3, 3, -1]) + assert (result == expected).all() From 236b91838514b844b98ae75bef836346f2439c3f Mon Sep 17 00:00:00 2001 From: Kaiqi Date: Mon, 30 Sep 2019 08:43:31 +0200 Subject: [PATCH 5/8] Code change based on reviews --- pandas/tests/indexes/test_range.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index d05ba64965fd0..30eb4c79ffd34 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -1056,8 +1056,8 @@ def test_reindex_limit(self): def test_get_indexer_limit(self): # GH 28631 - idx = Index(range(4)) - target = Index([0, 1, 2, 3, 4, 5]) + idx = RangeIndex(0, 4) + target = RangeIndex(0, 6) result = idx.get_indexer(target, method="pad", limit=1) expected = np.array([0, 1, 2, 3, 3, -1]) - assert (result == expected).all() + tm.assert_numpy_array_equal(result, expected, check_dtype=False) From 793c93c060c3dde8494c554643c4ac00c6ac7f7a Mon Sep 17 00:00:00 2001 From: Kaiqi Date: Mon, 30 Sep 2019 09:18:20 +0200 Subject: [PATCH 6/8] better pandas --- pandas/tests/indexes/test_range.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index 30eb4c79ffd34..b30e728be3cc8 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -416,6 +416,14 @@ def test_get_indexer_backfill(self): expected = np.array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5], dtype=np.intp) tm.assert_numpy_array_equal(indexer, expected) + def test_get_indexer_limit(self): + # GH 28631 + idx = RangeIndex(4) + target = RangeIndex(6) + result = idx.get_indexer(target, method="pad", limit=1) + expected = np.array([0, 1, 2, 3, 3, -1], dtype=np.intp) + tm.assert_numpy_array_equal(result, expected) + def test_join_outer(self): # join with Int64Index other = Int64Index(np.arange(25, 14, -1)) @@ -1053,11 +1061,3 @@ def test_reindex_limit(self): result = df.reindex([0, 1, 2, 3, 4, 5], method="ffill", limit=1) expected = pd.DataFrame(exp_data) tm.assert_frame_equal(result, expected) - - def test_get_indexer_limit(self): - # GH 28631 - idx = RangeIndex(0, 4) - target = RangeIndex(0, 6) - result = idx.get_indexer(target, method="pad", limit=1) - expected = np.array([0, 1, 2, 3, 3, -1]) - tm.assert_numpy_array_equal(result, expected, check_dtype=False) From 861e8ad546c52a139d565c5e85202c5df55dcd29 Mon Sep 17 00:00:00 2001 From: Kaiqi Date: Mon, 30 Sep 2019 19:52:02 +0200 Subject: [PATCH 7/8] code change based on review --- pandas/core/indexes/range.py | 1 - pandas/tests/frame/test_indexing.py | 16 ++++++++++++++++ pandas/tests/indexes/test_range.py | 16 ---------------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index 7560674bc0019..cd86689a5cc11 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -383,7 +383,6 @@ def get_indexer(self, target, method=None, limit=None, tolerance=None): if not ( method is None and tolerance is None - and limit is None and is_list_like(target) ): return super().get_indexer( diff --git a/pandas/tests/frame/test_indexing.py b/pandas/tests/frame/test_indexing.py index 6b073c460ea08..b88126b690d23 100644 --- a/pandas/tests/frame/test_indexing.py +++ b/pandas/tests/frame/test_indexing.py @@ -2217,6 +2217,22 @@ def test_reindex_frame_add_nat(self): assert mask[-5:].all() assert not mask[:-5].any() + def test_reindex_limit(self): + # GH 28631 + data = [["A", "A", "A"], ["B", "B", "B"], ["C", "C", "C"], ["D", "D", "D"]] + exp_data = [ + ["A", "A", "A"], + ["B", "B", "B"], + ["C", "C", "C"], + ["D", "D", "D"], + ["D", "D", "D"], + [np.nan, np.nan, np.nan], + ] + df = pd.DataFrame(data) + result = df.reindex([0, 1, 2, 3, 4, 5], method="ffill", limit=1) + expected = pd.DataFrame(exp_data) + tm.assert_frame_equal(result, expected) + def test_set_dataframe_column_ns_dtype(self): x = DataFrame([datetime.now(), datetime.now()]) assert x[0].dtype == np.dtype("M8[ns]") diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index b30e728be3cc8..7e08a5deaff7a 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -1045,19 +1045,3 @@ def test_engineless_lookup(self): assert idx.get_loc("a") == -1 assert "_engine" in idx._cache - - def test_reindex_limit(self): - # GH 28631 - data = [["A", "A", "A"], ["B", "B", "B"], ["C", "C", "C"], ["D", "D", "D"]] - exp_data = [ - ["A", "A", "A"], - ["B", "B", "B"], - ["C", "C", "C"], - ["D", "D", "D"], - ["D", "D", "D"], - [np.nan, np.nan, np.nan], - ] - df = pd.DataFrame(data) - result = df.reindex([0, 1, 2, 3, 4, 5], method="ffill", limit=1) - expected = pd.DataFrame(exp_data) - tm.assert_frame_equal(result, expected) From 35b56112c94b51a6df353367d617cf847d4b353f Mon Sep 17 00:00:00 2001 From: Kaiqi Date: Mon, 30 Sep 2019 23:20:10 +0200 Subject: [PATCH 8/8] code change on reviews --- pandas/core/indexes/range.py | 6 +----- pandas/tests/frame/test_indexing.py | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pandas/core/indexes/range.py b/pandas/core/indexes/range.py index cd86689a5cc11..43445a0d5d5a2 100644 --- a/pandas/core/indexes/range.py +++ b/pandas/core/indexes/range.py @@ -380,11 +380,7 @@ def get_loc(self, key, method=None, tolerance=None): @Appender(_index_shared_docs["get_indexer"]) def get_indexer(self, target, method=None, limit=None, tolerance=None): - if not ( - method is None - and tolerance is None - and is_list_like(target) - ): + if com.any_not_none(method, tolerance, limit) or not is_list_like(target): return super().get_indexer( target, method=method, tolerance=tolerance, limit=limit ) diff --git a/pandas/tests/frame/test_indexing.py b/pandas/tests/frame/test_indexing.py index b88126b690d23..6d239e96cd167 100644 --- a/pandas/tests/frame/test_indexing.py +++ b/pandas/tests/frame/test_indexing.py @@ -2228,9 +2228,9 @@ def test_reindex_limit(self): ["D", "D", "D"], [np.nan, np.nan, np.nan], ] - df = pd.DataFrame(data) + df = DataFrame(data) result = df.reindex([0, 1, 2, 3, 4, 5], method="ffill", limit=1) - expected = pd.DataFrame(exp_data) + expected = DataFrame(exp_data) tm.assert_frame_equal(result, expected) def test_set_dataframe_column_ns_dtype(self):