Skip to content

REF: is_subperiod, is_superperiod out of libfreqs #34387

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

Merged
merged 4 commits into from
May 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 0 additions & 160 deletions pandas/_libs/tslibs/frequencies.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ cnp.import_array()

from pandas._libs.tslibs.util cimport is_integer_object

from pandas._libs.tslibs.ccalendar cimport c_MONTH_NUMBERS
from pandas._libs.tslibs.offsets cimport is_offset_object
from pandas._libs.tslibs.parsing cimport get_rule_month

# ----------------------------------------------------------------------
# Constants
Expand Down Expand Up @@ -333,161 +331,3 @@ cpdef int get_to_timestamp_base(int base):
elif FreqGroup.FR_HR <= base <= FreqGroup.FR_SEC:
return FreqGroup.FR_SEC
return base


# ----------------------------------------------------------------------
# Frequency comparison

def is_subperiod(source, target) -> bint:
"""
Returns True if downsampling is possible between source and target
frequencies

Parameters
----------
source : string or DateOffset
Frequency converting from
target : string or DateOffset
Frequency converting to

Returns
-------
is_subperiod : boolean
"""

if target is None or source is None:
return False
source = _maybe_coerce_freq(source)
target = _maybe_coerce_freq(target)

if _is_annual(target):
if _is_quarterly(source):
return _quarter_months_conform(get_rule_month(source),
get_rule_month(target))
return source in {'D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'}
elif _is_quarterly(target):
return source in {'D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'}
elif _is_monthly(target):
return source in {'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif _is_weekly(target):
return source in {target, 'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif target == 'B':
return source in {'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif target == 'C':
return source in {'C', 'H', 'T', 'S', 'L', 'U', 'N'}
elif target == 'D':
return source in {'D', 'H', 'T', 'S', 'L', 'U', 'N'}
elif target == 'H':
return source in {'H', 'T', 'S', 'L', 'U', 'N'}
elif target == 'T':
return source in {'T', 'S', 'L', 'U', 'N'}
elif target == 'S':
return source in {'S', 'L', 'U', 'N'}
elif target == 'L':
return source in {'L', 'U', 'N'}
elif target == 'U':
return source in {'U', 'N'}
elif target == 'N':
return source in {'N'}


def is_superperiod(source, target) -> bint:
"""
Returns True if upsampling is possible between source and target
frequencies

Parameters
----------
source : string
Frequency converting from
target : string
Frequency converting to

Returns
-------
is_superperiod : boolean
"""
if target is None or source is None:
return False
source = _maybe_coerce_freq(source)
target = _maybe_coerce_freq(target)

if _is_annual(source):
if _is_annual(target):
return get_rule_month(source) == get_rule_month(target)

if _is_quarterly(target):
smonth = get_rule_month(source)
tmonth = get_rule_month(target)
return _quarter_months_conform(smonth, tmonth)
return target in {'D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'}
elif _is_quarterly(source):
return target in {'D', 'C', 'B', 'M', 'H', 'T', 'S', 'L', 'U', 'N'}
elif _is_monthly(source):
return target in {'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif _is_weekly(source):
return target in {source, 'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif source == 'B':
return target in {'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif source == 'C':
return target in {'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif source == 'D':
return target in {'D', 'C', 'B', 'H', 'T', 'S', 'L', 'U', 'N'}
elif source == 'H':
return target in {'H', 'T', 'S', 'L', 'U', 'N'}
elif source == 'T':
return target in {'T', 'S', 'L', 'U', 'N'}
elif source == 'S':
return target in {'S', 'L', 'U', 'N'}
elif source == 'L':
return target in {'L', 'U', 'N'}
elif source == 'U':
return target in {'U', 'N'}
elif source == 'N':
return target in {'N'}


cdef str _maybe_coerce_freq(code):
""" we might need to coerce a code to a rule_code
and uppercase it

Parameters
----------
source : string or DateOffset
Frequency converting from

Returns
-------
code : string
"""
assert code is not None
if is_offset_object(code):
# i.e. isinstance(code, DateOffset):
code = code.rule_code
return code.upper()


cdef bint _quarter_months_conform(str source, str target):
snum = c_MONTH_NUMBERS[source]
tnum = c_MONTH_NUMBERS[target]
return snum % 3 == tnum % 3


cdef bint _is_annual(str rule):
rule = rule.upper()
return rule == 'A' or rule.startswith('A-')


cdef bint _is_quarterly(str rule):
rule = rule.upper()
return rule == 'Q' or rule.startswith('Q-') or rule.startswith('BQ')


cdef bint _is_monthly(str rule):
rule = rule.upper()
return rule == 'M' or rule == 'BM'


cdef bint _is_weekly(str rule):
rule = rule.upper()
return rule == 'W' or rule.startswith('W-')
7 changes: 3 additions & 4 deletions pandas/core/resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from pandas._libs import lib
from pandas._libs.tslibs import NaT, Period, Timedelta, Timestamp
from pandas._libs.tslibs.frequencies import is_subperiod, is_superperiod
from pandas._libs.tslibs.period import IncompatibleFrequency
from pandas._typing import TimedeltaConvertibleTypes, TimestampConvertibleTypes
from pandas.compat.numpy import function as nv
Expand All @@ -29,7 +28,7 @@
from pandas.core.indexes.period import PeriodIndex, period_range
from pandas.core.indexes.timedeltas import TimedeltaIndex, timedelta_range

from pandas.tseries.frequencies import to_offset
from pandas.tseries.frequencies import is_subperiod, is_superperiod, to_offset
from pandas.tseries.offsets import DateOffset, Day, Nano, Tick

_shared_docs_kwargs: Dict[str, str] = dict()
Expand Down Expand Up @@ -1709,7 +1708,7 @@ def _get_timestamp_range_edges(
origin = origin.tz_localize(None)

first, last = _adjust_dates_anchored(
first, last, freq, closed=closed, origin=origin, offset=offset,
first, last, freq, closed=closed, origin=origin, offset=offset
)
if isinstance(freq, Day):
first = first.tz_localize(index_tz)
Expand Down Expand Up @@ -1771,7 +1770,7 @@ def _get_period_range_edges(
adjust_last = freq.is_on_offset(last)

first, last = _get_timestamp_range_edges(
first, last, freq, closed=closed, origin=origin, offset=offset,
first, last, freq, closed=closed, origin=origin, offset=offset
)

first = (first + int(adjust_first) * freq).to_period(freq)
Expand Down
9 changes: 2 additions & 7 deletions pandas/plotting/_matplotlib/timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@

import numpy as np

from pandas._libs.tslibs.frequencies import (
FreqGroup,
base_and_stride,
get_freq_code,
is_subperiod,
is_superperiod,
)
from pandas._libs.tslibs.frequencies import FreqGroup, base_and_stride, get_freq_code
from pandas._libs.tslibs.period import Period

from pandas.core.dtypes.generic import (
Expand All @@ -27,6 +21,7 @@
TimeSeries_TimedeltaFormatter,
)
import pandas.tseries.frequencies as frequencies
from pandas.tseries.frequencies import is_subperiod, is_superperiod
from pandas.tseries.offsets import DateOffset

# ---------------------------------------------------------------------
Expand Down
8 changes: 2 additions & 6 deletions pandas/tests/tslibs/test_libfrequencies.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import pytest

from pandas._libs.tslibs.frequencies import (
INVALID_FREQ_ERR_MSG,
_period_str_to_code,
is_subperiod,
is_superperiod,
)
from pandas._libs.tslibs.frequencies import INVALID_FREQ_ERR_MSG, _period_str_to_code
from pandas._libs.tslibs.parsing import get_rule_month

from pandas.tseries import offsets
from pandas.tseries.frequencies import is_subperiod, is_superperiod # TODO: move tests


@pytest.mark.parametrize(
Expand Down
Loading