Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: consistency of input args for boundaries in DataFrame.between_time() #40245 #43248

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
2a38350
boundary inputs updated for DataFrame.between_time function
suyashgupta01 Aug 24, 2021
4272175
addev virtual environment to gitignore
suyashgupta01 Aug 26, 2021
ce929d2
added env to gitignore
suyashgupta01 Aug 26, 2021
113615e
resolved
suyashgupta01 Aug 26, 2021
e0924f6
tests work now
suyashgupta01 Aug 27, 2021
b12957b
comments updated
suyashgupta01 Aug 27, 2021
f1a0641
deleted test_between_time.py backup (duplicate)
suyashgupta01 Aug 27, 2021
a7032c4
removed unused import
suyashgupta01 Aug 27, 2021
cb2ca4d
linting improvement
suyashgupta01 Aug 27, 2021
c7f24de
aremoved debug print statements
suyashgupta01 Aug 27, 2021
30be004
linting improvements
suyashgupta01 Aug 27, 2021
ff83813
Merge branch 'pandas-dev:master' into master
suyashgupta01 Aug 27, 2021
83cd360
linting improvement
suyashgupta01 Aug 27, 2021
6aacf78
merging
suyashgupta01 Aug 27, 2021
c94b34d
updated docstring for between_time()
suyashgupta01 Aug 27, 2021
1e36cb2
made whats new entry
suyashgupta01 Aug 27, 2021
1e6361b
linting improvement
suyashgupta01 Aug 27, 2021
236b8c3
updated docstring for inclusive
suyashgupta01 Aug 28, 2021
01bf00e
making if statements consistent
suyashgupta01 Aug 28, 2021
5b35ac7
precommit hook added
suyashgupta01 Aug 30, 2021
ce00141
modified gitignore as per review
suyashgupta01 Aug 30, 2021
99f35c3
deleted .github/.pre-commit-config.yaml as per review
suyashgupta01 Aug 30, 2021
101c0c2
bool_t: reconverted from string to annotation as per review
suyashgupta01 Aug 30, 2021
40faba2
Merge branch 'pandas-dev:master' into master
suyashgupta01 Aug 30, 2021
6e9882d
fetch from master and merge
suyashgupta01 Aug 30, 2021
d447d6b
used lib.no_default as per review
suyashgupta01 Aug 30, 2021
69a2891
preccommit hook changes
suyashgupta01 Aug 31, 2021
226b961
removed venv files
suyashgupta01 Aug 31, 2021
6e3c42b
Merge branch 'pandas-dev:master' into master
suyashgupta01 Aug 31, 2021
28cf632
fetched from upstream and merge
suyashgupta01 Aug 31, 2021
2bb5c5a
Update pandas/core/generic.py to preserve args order
suyashgupta01 Aug 31, 2021
06d964c
Update pandas/core/generic.py to preserve args order in docstring
suyashgupta01 Aug 31, 2021
4946857
Update pandas/core/generic.py as per suggestion
suyashgupta01 Aug 31, 2021
8df4bb6
linting improvement
suyashgupta01 Aug 31, 2021
3dcfd0b
test_between_time modified to accomodate previous review changes
suyashgupta01 Aug 31, 2021
5c013e3
Merge branch 'master' into new-boundary-inputs-pandas.DataFrame.betwe…
suyashgupta01 Aug 31, 2021
7dbc6c4
updated docstring for CI error
suyashgupta01 Aug 31, 2021
ccd35cd
removed fixture as per review
suyashgupta01 Aug 31, 2021
f255d5e
removed redundant msg as per review
suyashgupta01 Aug 31, 2021
e9f109f
removed redundant code
suyashgupta01 Sep 1, 2021
c1f3f86
error when user passes both new and depreciated args
suyashgupta01 Sep 1, 2021
b26cc5c
changed default value of inclusive to None fromm empty str
suyashgupta01 Sep 1, 2021
5e3e193
ValueError message changed when both depreciated args and new args pa…
suyashgupta01 Sep 2, 2021
3bcb185
comment updated when inclusive defaults to both
suyashgupta01 Sep 2, 2021
63975b4
added deprecated directive for include_start and include_end
suyashgupta01 Sep 2, 2021
50cc20c
deprecated directive updated
suyashgupta01 Sep 2, 2021
4b6d817
version corrected in depreciate directive
suyashgupta01 Sep 2, 2021
1745349
Updated ValueError message as per review
suyashgupta01 Sep 3, 2021
2f60ba2
Merge branch 'pandas-dev:master' into master
suyashgupta01 Sep 3, 2021
b5043cb
Fetch and merge
suyashgupta01 Sep 3, 2021
da075f3
updated docstring for between_time
suyashgupta01 Sep 3, 2021
14e5450
test_between_time_incorr_arg_inclusive added
suyashgupta01 Sep 4, 2021
8987d17
tests added
suyashgupta01 Sep 4, 2021
693ad71
depreciated -> deprecated
suyashgupta01 Sep 4, 2021
f49126b
default type for inclusive mentioned as str
suyashgupta01 Sep 4, 2021
6951d25
added message to match for FutureWarning in test_between_time_warn
suyashgupta01 Sep 4, 2021
0569ce3
typo fix: added space to a ValueError message
suyashgupta01 Sep 4, 2021
8d5d8c6
default values updated for include_start, include_end
suyashgupta01 Sep 4, 2021
faabfdb
added missing functionality, modified test case for it
suyashgupta01 Sep 4, 2021
12c787d
modified between_time as per suggestion
suyashgupta01 Sep 4, 2021
5dae3f0
Removed incorrect spaces from docstring for correct rendering
suyashgupta01 Sep 4, 2021
56966f0
Merge branch 'master' into new-boundary-inputs-pandas.DataFrame.betwe…
suyashgupta01 Sep 6, 2021
241c6a7
Modified test_between_time_incorr_arg_inclusive as per suggestion
suyashgupta01 Sep 6, 2021
c0f0ada
test_between_time_incompatiable_args_given parametrized
suyashgupta01 Sep 6, 2021
e883702
test added to assert functionality on both old, new args
suyashgupta01 Sep 6, 2021
bb61353
infavour -> in favour
suyashgupta01 Sep 6, 2021
605e144
docstring update as per suggestion
suyashgupta01 Sep 6, 2021
2ecb812
git pull from remote
suyashgupta01 Sep 6, 2021
38a2aa1
mpyerror fixed
suyashgupta01 Sep 6, 2021
dcafe0c
changed order of args as per suggestion in between_time
suyashgupta01 Sep 7, 2021
84543b8
replaced parametrize with fixture as per suggestion in test_between_time
suyashgupta01 Sep 7, 2021
48bd780
readability update in test_between_time.py
suyashgupta01 Sep 7, 2021
6eb02d7
comment # GH40245 shifted inside test definitions
suyashgupta01 Sep 7, 2021
519113b
readability update x,y -> result, expected
suyashgupta01 Sep 7, 2021
b701430
used assert_frame_equal ito compare frames
suyashgupta01 Sep 7, 2021
938d39a
updated generic.py
suyashgupta01 Sep 7, 2021
fdfa53f
removed comment as per suggestion
suyashgupta01 Sep 8, 2021
0796bc4
added , default True iin docstring for inc_start, inc_end in between_…
suyashgupta01 Sep 8, 2021
b1fa8d6
close -> closed as per suggestion
suyashgupta01 Sep 10, 2021
6c10418
close -> closed as per suggestion
suyashgupta01 Sep 10, 2021
186b7a3
added a space in ValueError msg for readability
suyashgupta01 Sep 10, 2021
ba02ad1
git pull and merge
suyashgupta01 Sep 10, 2021
63de5a2
Merge branch 'master' into new-boundary-inputs-pandas.DataFrame.betwe…
suyashgupta01 Sep 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v1.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ Other enhancements
- Methods that relied on hashmap based algos such as :meth:`DataFrameGroupBy.value_counts`, :meth:`DataFrameGroupBy.count` and :func:`factorize` ignored imaginary component for complex numbers (:issue:`17927`)
- Add :meth:`Series.str.removeprefix` and :meth:`Series.str.removesuffix` introduced in Python 3.9 to remove pre-/suffixes from string-type :class:`Series` (:issue:`36944`)


.. ---------------------------------------------------------------------------

.. _whatsnew_140.notable_bug_fixes:
Expand Down Expand Up @@ -278,6 +279,7 @@ Other Deprecations
- Deprecated :meth:`Index.reindex` with a non-unique index (:issue:`42568`)
- Deprecated :meth:`.Styler.render` in favour of :meth:`.Styler.to_html` (:issue:`42140`)
- Deprecated passing in a string column label into ``times`` in :meth:`DataFrame.ewm` (:issue:`43265`)
- Deprecated the 'include_start' and 'include_end' arguments in :meth:`DataFrame.between_time`; in a future version passing 'include_start' or 'include_end' will raise (:issue:`40245`)
- Deprecated the ``squeeze`` argument to :meth:`read_csv`, :meth:`read_table`, and :meth:`read_excel`. Users should squeeze the DataFrame afterwards with ``.squeeze("columns")`` instead. (:issue:`43242`)

.. ---------------------------------------------------------------------------
Expand Down
57 changes: 54 additions & 3 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7606,8 +7606,9 @@ def between_time(
self: FrameOrSeries,
start_time,
end_time,
include_start: bool_t = True,
include_end: bool_t = True,
include_start: bool_t | lib.NoDefault = lib.no_default,
include_end: bool_t | lib.NoDefault = lib.no_default,
inclusive: str | None = None,
axis=None,
) -> FrameOrSeries:
"""
Expand All @@ -7624,8 +7625,20 @@ def between_time(
End time as a time filter limit.
include_start : bool, default True
Whether the start time needs to be included in the result.

.. deprecated:: 1.4.0
Arguments `include_start` and `include_end` have been deprecated
to standardize boundary inputs. Use `inclusive` instead, to set
each bound as closed or open.
include_end : bool, default True
Whether the end time needs to be included in the result.

.. deprecated:: 1.4.0
Arguments `include_start` and `include_end` have been deprecated
to standardize boundary inputs. Use `inclusive` instead, to set
each bound as closed or open.
inclusive : {"both", "neither", "left", "right"}, default "both"
jreback marked this conversation as resolved.
Show resolved Hide resolved
Include boundaries; whether to set each bound as closed or open.
axis : {0 or 'index', 1 or 'columns'}, default 0
Determine range time on index or columns value.

Expand Down Expand Up @@ -7679,8 +7692,46 @@ def between_time(
if not isinstance(index, DatetimeIndex):
raise TypeError("Index must be DatetimeIndex")

if (include_start != lib.no_default or include_end != lib.no_default) and (
inclusive is not None
):
raise ValueError(
suyashgupta01 marked this conversation as resolved.
Show resolved Hide resolved
"Deprecated arguments `include_start` and `include_end` "
"cannot be passed if `inclusive` has been given."
)
# If any of the deprecated arguments ('include_start', 'include_end')
# have been passed
elif (include_start != lib.no_default) or (include_end != lib.no_default):
warnings.warn(
"`include_start` and `include_end` are deprecated in "
"favour of `inclusive`.",
FutureWarning,
stacklevel=2,
)
left = True if isinstance(include_start, lib.NoDefault) else include_start
right = True if isinstance(include_end, lib.NoDefault) else include_end

inc_dict = {
(True, True): "both",
(True, False): "left",
(False, True): "right",
(False, False): "neither",
}
inclusive = inc_dict[(left, right)]
else: # On arg removal inclusive can default to "both"
if inclusive is None:
inclusive = "both"
suyashgupta01 marked this conversation as resolved.
Show resolved Hide resolved
elif inclusive not in ["both", "neither", "left", "right"]:
raise ValueError(
f"Inclusive has to be either string of 'both', "
f"'left', 'right', or 'neither'. Got {inclusive}."
)

indexer = index.indexer_between_time(
start_time, end_time, include_start=include_start, include_end=include_end
start_time,
end_time,
include_start=inclusive in ["both", "left"],
include_end=inclusive in ["both", "right"],
)
return self._take_with_is_copy(indexer, axis=axis)

Expand Down
6 changes: 2 additions & 4 deletions pandas/tests/frame/conftest.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from itertools import product

import numpy as np
import pytest

Expand All @@ -11,8 +9,8 @@
import pandas._testing as tm


@pytest.fixture(params=product([True, False], [True, False]))
def close_open_fixture(request):
@pytest.fixture(params=["both", "neither", "left", "right"])
def inclusive_endpoints_fixture(request):
return request.param


Expand Down
113 changes: 101 additions & 12 deletions pandas/tests/frame/methods/test_between_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,32 +69,33 @@ def test_between_time_types(self, frame_or_series):
with pytest.raises(ValueError, match=msg):
obj.between_time(datetime(2010, 1, 2, 1), datetime(2010, 1, 2, 5))

def test_between_time(self, close_open_fixture, frame_or_series):
def test_between_time(self, inclusive_endpoints_fixture, frame_or_series):
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)
if frame_or_series is not DataFrame:
ts = ts[0]

stime = time(0, 0)
etime = time(1, 0)
inc_start, inc_end = close_open_fixture
inclusive = inclusive_endpoints_fixture

filtered = ts.between_time(stime, etime, inc_start, inc_end)
filtered = ts.between_time(stime, etime, inclusive=inclusive)
exp_len = 13 * 4 + 1
if not inc_start:

if inclusive in ["right", "neither"]:
exp_len -= 5
if not inc_end:
if inclusive in ["left", "neither"]:
exp_len -= 4

assert len(filtered) == exp_len
for rs in filtered.index:
t = rs.time()
if inc_start:
if inclusive in ["left", "both"]:
assert t >= stime
else:
assert t > stime

if inc_end:
if inclusive in ["right", "both"]:
assert t <= etime
else:
assert t < etime
Expand All @@ -111,22 +112,22 @@ def test_between_time(self, close_open_fixture, frame_or_series):
stime = time(22, 0)
etime = time(9, 0)

filtered = ts.between_time(stime, etime, inc_start, inc_end)
filtered = ts.between_time(stime, etime, inclusive=inclusive)
exp_len = (12 * 11 + 1) * 4 + 1
if not inc_start:
if inclusive in ["right", "neither"]:
exp_len -= 4
if not inc_end:
if inclusive in ["left", "neither"]:
exp_len -= 4

assert len(filtered) == exp_len
for rs in filtered.index:
t = rs.time()
if inc_start:
if inclusive in ["left", "both"]:
assert (t >= stime) or (t <= etime)
else:
assert (t > stime) or (t <= etime)

if inc_end:
if inclusive in ["right", "both"]:
assert (t <= etime) or (t >= stime)
else:
assert (t < etime) or (t >= stime)
Expand Down Expand Up @@ -207,3 +208,91 @@ def test_between_time_datetimeindex(self):
tm.assert_frame_equal(result, expected)
tm.assert_frame_equal(result, expected2)
assert len(result) == 12

@pytest.mark.parametrize("include_start", [True, False])
@pytest.mark.parametrize("include_end", [True, False])
def test_between_time_warn(self, include_start, include_end, frame_or_series):
# GH40245
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)
if frame_or_series is not DataFrame:
ts = ts[0]

stime = time(0, 0)
etime = time(1, 0)

match = (
"`include_start` and `include_end` "
"are deprecated in favour of `inclusive`."
)
with tm.assert_produces_warning(FutureWarning, match=match):
_ = ts.between_time(stime, etime, include_start, include_end)

def test_between_time_incorr_arg_inclusive(self):
# GH40245
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)

stime = time(0, 0)
etime = time(1, 0)
inclusive = "bad_string"
msg = (
"Inclusive has to be either string of 'both', 'left', 'right', "
"or 'neither'. Got bad_string."
)
with pytest.raises(ValueError, match=msg):
ts.between_time(stime, etime, inclusive=inclusive)

@pytest.mark.parametrize(
"include_start, include_end", [(True, None), (True, True), (None, True)]
)
def test_between_time_incompatiable_args_given(self, include_start, include_end):
# GH40245
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)

stime = time(0, 0)
etime = time(1, 0)
msg = (
"Deprecated arguments `include_start` and `include_end` cannot be "
"passed if `inclusive` has been given."
)
with pytest.raises(ValueError, match=msg):
ts.between_time(stime, etime, include_start, include_end, inclusive="left")

def test_between_time_same_functionality_old_and_new_args(self):
# GH40245
rng = date_range("1/1/2000", "1/5/2000", freq="5min")
ts = DataFrame(np.random.randn(len(rng), 2), index=rng)
stime = time(0, 0)
etime = time(1, 0)
match = (
"`include_start` and `include_end` "
"are deprecated in favour of `inclusive`."
)

result = ts.between_time(stime, etime)
expected = ts.between_time(stime, etime, inclusive="both")
tm.assert_frame_equal(result, expected)

with tm.assert_produces_warning(FutureWarning, match=match):
result = ts.between_time(stime, etime, include_start=False)
expected = ts.between_time(stime, etime, inclusive="right")
tm.assert_frame_equal(result, expected)

with tm.assert_produces_warning(FutureWarning, match=match):
result = ts.between_time(stime, etime, include_end=False)
expected = ts.between_time(stime, etime, inclusive="left")
tm.assert_frame_equal(result, expected)

with tm.assert_produces_warning(FutureWarning, match=match):
result = ts.between_time(
stime, etime, include_start=False, include_end=False
)
expected = ts.between_time(stime, etime, inclusive="neither")
tm.assert_frame_equal(result, expected)

with tm.assert_produces_warning(FutureWarning, match=match):
result = ts.between_time(stime, etime, include_start=True, include_end=True)
expected = ts.between_time(stime, etime, inclusive="both")
tm.assert_frame_equal(result, expected)