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 (pd.date_range) #43504

Merged
merged 10 commits into from Oct 3, 2021

Conversation

zyc09
Copy link
Contributor

@zyc09 zyc09 commented Sep 10, 2021

closes #43394

xref #40245

  • tests added / passed
  • Ensure all linting tests pass, see here for how to run them
  • whatsnew entry

@@ -1823,6 +1823,37 @@ def validate_periods(periods):
return periods


def validate_inclusiveness(inclusive):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just call this validate_inclusive?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple of things. I would like to move this new routine & validate_entpoint to pandas/core/indexers/utils.py i think.
Also need to slightly refactor .between_time (which was just merged) to use the same.

Might be best to do these as a pre-cursor PR to this one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might also look at other merged prs from underlying issue that may be able to use this validator,

@@ -1823,6 +1823,37 @@ def validate_periods(periods):
return periods


def validate_inclusiveness(inclusive):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple of things. I would like to move this new routine & validate_entpoint to pandas/core/indexers/utils.py i think.
Also need to slightly refactor .between_time (which was just merged) to use the same.

Might be best to do these as a pre-cursor PR to this one.

closed = date_range(begin, end, closed=None, freq=freq)
left = date_range(begin, end, closed="left", freq=freq)
right = date_range(begin, end, closed="right", freq=freq)
both = date_range(begin, end, inclusive="both", freq=freq)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you parameterize this test instead, using the inclusive_endpoints_fixture fixtures (its in pandas/tests/frameso likely need to move topandas/conftest.py`

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea makes sense, will do that

closed = date_range(begin, end, closed=None, freq=freq)
left = date_range(begin, end, closed="left", freq=freq)
right = date_range(begin, end, closed="right", freq=freq)
both = date_range(begin, end, inclusive="both", freq=freq)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

closed = date_range(begin, end, closed=None, freq=freq, tz="US/Eastern")
left = date_range(begin, end, closed="left", freq=freq, tz="US/Eastern")
right = date_range(begin, end, closed="right", freq=freq, tz="US/Eastern")
both = date_range(begin, end, inclusive="both", freq=freq, tz="US/Eastern")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same


@pytest.mark.parametrize("closed", ["right", "left", None])
def test_range_closed_boundary(self, closed):
@pytest.mark.parametrize("inclusive", ["right", "left", "both", "neither"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

@jreback jreback added Deprecate Functionality to remove in pandas Timeseries labels Sep 12, 2021
@jreback
Copy link
Contributor

jreback commented Sep 12, 2021

is this also closing #43394 ? e.g. a bug fix, if so this needs a separate note

@zyc09
Copy link
Contributor Author

zyc09 commented Sep 13, 2021

is this also closing #43394 ? e.g. a bug fix, if so this needs a separate note

What do you mean by separate note by the way?

@jreback
Copy link
Contributor

jreback commented Sep 14, 2021

go ahead and rebase this

# and removing would leave index empty
to_remove_any = not (
(left_inclusive or right_inclusive)
and len(index) == 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be len(index) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mm yeah, changed that and changed the tests in test_date_range

@jreback jreback added this to the 1.4 milestone Sep 14, 2021
@@ -299,6 +299,11 @@ def nselect_method(request):
return request.param


@pytest.fixture(params=["both", "neither", "left", "right"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you put next to this one and add a doc-string that is indicative

@pytest.fixture(params=["left", "right", "both", "neither"])
def closed(request):
    """
    Fixture for trying all interval closed parameters.
    """
    return request.param

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking good a few comments

Argument `closed` 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"
Include boundaries; Whether to set each bound as closed or open.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

versionadded 1.4.0

left_match = begin == both_range[0]
right_match = end == both_range[-1]

if inclusive_endpoints_fixture == "left" and right_match:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider making this a function and share among these tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I defined the function on the top of the test_date_range.py file, does it belong elsewhere?

right_match = endtz == both_range[-1]

if inclusive_endpoints_fixture == "left" and right_match:
expected_range = both_range[:-1]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same (so we don't repeat ourselves)

Comment on lines 483 to 486
(left_inclusive or right_inclusive)
and len(index)
and start == index[0]
and start == end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when is start != index[0]?
when is len(index) == 0 i.e. when will len(index) resolve as False?
when is start == end?
Do any of these cases imply the others?

)

if to_remove_any:
if (not left_inclusive) and len(index) and index[0] == start:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are reusing the same logic tests deriving to_remove_any. I haven't come up with a better way but instinctively this feels a complicated logic path. Have you tried refactoring to a simpler setup?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I refactored the logic a little and I am not sure if it is any better though

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgttm. @attack68 if comments

@@ -1029,6 +1038,28 @@ def date_range(
DatetimeIndex(['2017-01-02', '2017-01-03', '2017-01-04'],
dtype='datetime64[ns]', freq='D')
"""
if inclusive is not None and not isinstance(closed, lib.NoDefault):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its possible we would want to share this (across functoions), but ok here

@jreback
Copy link
Contributor

jreback commented Sep 15, 2021

https://github.com/pandas-dev/pandas/pull/43504/checks?check_run_id=3612446736

couple of tests that need addressing (you can either assert the future warning or just change closed -> inclusive in the test)

Copy link
Contributor

@attack68 attack68 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm pending green tests and some grammar corrections.

@@ -919,6 +920,14 @@ def date_range(
closed : {None, 'left', 'right'}, optional
Make the interval closed with respect to the given frequency to
the 'left', 'right', or both sides (None, the default).

.. deprecated:: 1.4.0
Argument `closed` have been deprecated to standardize boundary inputs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'has' not 'have'.

@@ -1090,6 +1122,14 @@ def bdate_range(
closed : str, default None
Make the interval closed with respect to the given frequency to
the 'left', 'right', or both sides (None).

.. deprecated:: 1.4.0
Argument `closed` have been deprecated to standardize boundary inputs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'has'

@jreback
Copy link
Contributor

jreback commented Sep 28, 2021

some comments & can you merge master. ping on green.

@attack68 attack68 merged commit 3db765a into pandas-dev:master Oct 3, 2021
@attack68
Copy link
Contributor

attack68 commented Oct 3, 2021

thanks @zyc09

gasparitiago pushed a commit to gasparitiago/pandas that referenced this pull request Oct 9, 2021
…-dev#43504)

Co-authored-by: JHM Darbyshire <24256554+attack68@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Deprecate Functionality to remove in pandas Enhancement Timeseries
Projects
None yet
Development

Successfully merging this pull request may close these issues.

pd.date_range function not returns right bound when start=end and closed set to 'right'
3 participants