def test_frequency_misc(self): assert (resolution.get_freq_group('T') == FreqGroup.FR_MIN) code, stride = get_freq_code(offsets.Hour()) assert code == FreqGroup.FR_HR code, stride = get_freq_code((5, 'T')) assert code == FreqGroup.FR_MIN assert stride == 5 offset = offsets.Hour() result = frequencies.to_offset(offset) assert result == offset result = frequencies.to_offset((5, 'T')) expected = offsets.Minute(5) assert result == expected with pytest.raises(ValueError, match='Invalid frequency'): get_freq_code((5, 'baz')) with pytest.raises(ValueError, match='Invalid frequency'): frequencies.to_offset('100foo') with pytest.raises(ValueError, match='Could not evaluate'): frequencies.to_offset(('', ''))
def _range_from_fields(year=None, month=None, quarter=None, day=None, hour=None, minute=None, second=None, freq=None): if hour is None: hour = 0 if minute is None: minute = 0 if second is None: second = 0 if day is None: day = 1 ordinals = [] if quarter is not None: if freq is None: freq = 'Q' base = libfrequencies.FreqGroup.FR_QTR else: base, mult = libfrequencies.get_freq_code(freq) if base != libfrequencies.FreqGroup.FR_QTR: raise AssertionError("base must equal FR_QTR") year, quarter = _make_field_arrays(year, quarter) for y, q in zip(year, quarter): y, m = libperiod.quarter_to_myear(y, q, freq) val = libperiod.period_ordinal(y, m, 1, 1, 1, 1, 0, 0, base) ordinals.append(val) else: base, mult = libfrequencies.get_freq_code(freq) arrays = _make_field_arrays(year, month, day, hour, minute, second) for y, mth, d, h, mn, s in zip(*arrays): ordinals.append(libperiod.period_ordinal( y, mth, d, h, mn, s, 0, 0, base)) return np.array(ordinals, dtype=np.int64), freq
def asfreq(self, freq=None, how='E'): """ Convert the Period Array/Index to the specified frequency `freq`. Parameters ---------- freq : str a frequency how : str {'E', 'S'} 'E', 'END', or 'FINISH' for end, 'S', 'START', or 'BEGIN' for start. Whether the elements should be aligned to the end or start within pa period. January 31st ('END') vs. January 1st ('START') for example. Returns ------- new : Period Array/Index with the new frequency Examples -------- >>> pidx = pd.period_range('2010-01-01', '2015-01-01', freq='A') >>> pidx <class 'pandas.core.indexes.period.PeriodIndex'> [2010, ..., 2015] Length: 6, Freq: A-DEC >>> pidx.asfreq('M') <class 'pandas.core.indexes.period.PeriodIndex'> [2010-12, ..., 2015-12] Length: 6, Freq: M >>> pidx.asfreq('M', how='S') <class 'pandas.core.indexes.period.PeriodIndex'> [2010-01, ..., 2015-01] Length: 6, Freq: M """ how = libperiod._validate_end_alias(how) freq = Period._maybe_convert_freq(freq) base1, mult1 = libfrequencies.get_freq_code(self.freq) base2, mult2 = libfrequencies.get_freq_code(freq) asi8 = self.asi8 # mult1 can't be negative or 0 end = how == 'E' if end: ordinal = asi8 + mult1 - 1 else: ordinal = asi8 new_data = period_asfreq_arr(ordinal, base1, base2, end) if self._hasnans: new_data[self._isnan] = iNaT return type(self)(new_data, freq=freq)
def asfreq(self, freq=None, how="E"): """ Convert the Period Array/Index to the specified frequency `freq`. Parameters ---------- freq : str A frequency. how : str {'E', 'S'} Whether the elements should be aligned to the end or start within pa period. * 'E', 'END', or 'FINISH' for end, * 'S', 'START', or 'BEGIN' for start. January 31st ('END') vs. January 1st ('START') for example. Returns ------- Period Array/Index Constructed with the new frequency. Examples -------- >>> pidx = pd.period_range('2010-01-01', '2015-01-01', freq='A') >>> pidx PeriodIndex(['2010', '2011', '2012', '2013', '2014', '2015'], dtype='period[A-DEC]', freq='A-DEC') >>> pidx.asfreq('M') PeriodIndex(['2010-12', '2011-12', '2012-12', '2013-12', '2014-12', '2015-12'], dtype='period[M]', freq='M') >>> pidx.asfreq('M', how='S') PeriodIndex(['2010-01', '2011-01', '2012-01', '2013-01', '2014-01', '2015-01'], dtype='period[M]', freq='M') """ how = libperiod._validate_end_alias(how) freq = Period._maybe_convert_freq(freq) base1, mult1 = libfrequencies.get_freq_code(self.freq) base2, mult2 = libfrequencies.get_freq_code(freq) asi8 = self.asi8 # mult1 can't be negative or 0 end = how == "E" if end: ordinal = asi8 + mult1 - 1 else: ordinal = asi8 new_data = period_asfreq_arr(ordinal, base1, base2, end) if self._hasnans: new_data[self._isnan] = iNaT return type(self)(new_data, freq=freq)
def _use_dynamic_x(ax, data: "FrameOrSeriesUnion") -> bool: freq = _get_index_freq(data.index) ax_freq = _get_ax_freq(ax) if freq is None: # convert irregular if axes has freq info freq = ax_freq else: # do not use tsplot if irregular was plotted first if (ax_freq is None) and (len(ax.get_lines()) > 0): return False if freq is None: return False freq = _get_period_alias(freq) if freq is None: return False # FIXME: hack this for 0.10.1, creating more technical debt...sigh if isinstance(data.index, ABCDatetimeIndex): base = get_freq_code(freq)[0] x = data.index if base <= FreqGroup.FR_DAY: return x[:1].is_normalized return Period(x[0], freq).to_timestamp().tz_localize(x.tz) == x[0] return True
def _range_from_fields( year=None, month=None, quarter=None, day=None, hour=None, minute=None, second=None, freq=None, ): if hour is None: hour = 0 if minute is None: minute = 0 if second is None: second = 0 if day is None: day = 1 ordinals = [] if quarter is not None: if freq is None: freq = "Q" base = libfrequencies.FreqGroup.FR_QTR else: base, mult = libfrequencies.get_freq_code(freq) if base != libfrequencies.FreqGroup.FR_QTR: raise AssertionError("base must equal FR_QTR") year, quarter = _make_field_arrays(year, quarter) for y, q in zip(year, quarter): y, m = libperiod.quarter_to_myear(y, q, freq) val = libperiod.period_ordinal(y, m, 1, 1, 1, 1, 0, 0, base) ordinals.append(val) else: base, mult = libfrequencies.get_freq_code(freq) arrays = _make_field_arrays(year, month, day, hour, minute, second) for y, mth, d, h, mn, s in zip(*arrays): ordinals.append( libperiod.period_ordinal(y, mth, d, h, mn, s, 0, 0, base)) return np.array(ordinals, dtype=np.int64), freq
def to_timestamp(self, freq=None, how="start"): """ Cast to DatetimeArray/Index. Parameters ---------- freq : str or DateOffset, optional Target frequency. The default is 'D' for week or longer, 'S' otherwise. how : {'s', 'e', 'start', 'end'} Whether to use the start or end of the time period being converted. Returns ------- DatetimeArray/Index """ from pandas.core.arrays import DatetimeArray how = libperiod._validate_end_alias(how) end = how == "E" if end: if freq == "B": # roll forward to ensure we land on B date adjust = Timedelta(1, "D") - Timedelta(1, "ns") return self.to_timestamp(how="start") + adjust else: adjust = Timedelta(1, "ns") return (self + self.freq).to_timestamp(how="start") - adjust if freq is None: base, mult = libfrequencies.get_freq_code(self.freq) freq = libfrequencies.get_to_timestamp_base(base) else: freq = Period._maybe_convert_freq(freq) base, mult = libfrequencies.get_freq_code(freq) new_data = self.asfreq(freq, how=how) new_data = libperiod.periodarr_to_dt64arr(new_data.asi8, base) return DatetimeArray(new_data)._with_freq("infer")
def __init__(self, freq, minor_locator=False, dynamic_mode=True, plot_obj=None): if isinstance(freq, str): freq = get_freq_code(freq)[0] self.format = None self.freq = freq self.locs = [] self.formatdict = None self.isminor = minor_locator self.isdynamic = dynamic_mode self.offset = 0 self.plot_obj = plot_obj self.finder = get_finder(freq)
def to_timestamp(self, freq=None, how='start'): """ Cast to DatetimeArray/Index. Parameters ---------- freq : string or DateOffset, optional Target frequency. The default is 'D' for week or longer, 'S' otherwise how : {'s', 'e', 'start', 'end'} Returns ------- DatetimeArray/Index """ from pandas.core.arrays import DatetimeArray how = libperiod._validate_end_alias(how) end = how == 'E' if end: if freq == 'B': # roll forward to ensure we land on B date adjust = Timedelta(1, 'D') - Timedelta(1, 'ns') return self.to_timestamp(how='start') + adjust else: adjust = Timedelta(1, 'ns') return (self + self.freq).to_timestamp(how='start') - adjust if freq is None: base, mult = libfrequencies.get_freq_code(self.freq) freq = libfrequencies.get_to_timestamp_base(base) else: freq = Period._maybe_convert_freq(freq) base, mult = libfrequencies.get_freq_code(freq) new_data = self.asfreq(freq, how=how) new_data = libperiod.periodarr_to_dt64arr(new_data.asi8, base) return DatetimeArray._from_sequence(new_data, freq='infer')
def get_finder(freq): if isinstance(freq, str): freq = get_freq_code(freq)[0] fgroup = get_freq_group(freq) if fgroup == FreqGroup.FR_ANN: return _annual_finder elif fgroup == FreqGroup.FR_QTR: return _quarterly_finder elif freq == FreqGroup.FR_MTH: return _monthly_finder elif (freq >= FreqGroup.FR_BUS) or fgroup == FreqGroup.FR_WK: return _daily_finder else: # pragma: no cover raise NotImplementedError(f"Unsupported frequency: {freq}")
def get_freq(freq): """ Return frequency code of given frequency str. If input is not string, return input as it is. Example ------- >>> get_freq('A') 1000 >>> get_freq('3A') 1000 """ if isinstance(freq, compat.string_types): base, mult = get_freq_code(freq) freq = base return freq
def _get_ordinal_range(start, end, periods, freq, mult=1): if com.count_not_none(start, end, periods) != 2: raise ValueError("Of the three parameters: start, end, and periods, " "exactly two must be specified") if freq is not None: _, mult = libfrequencies.get_freq_code(freq) if start is not None: start = Period(start, freq) if end is not None: end = Period(end, freq) is_start_per = isinstance(start, Period) is_end_per = isinstance(end, Period) if is_start_per and is_end_per and start.freq != end.freq: raise ValueError("start and end must have same freq") if start is NaT or end is NaT: raise ValueError("start and end must not be NaT") if freq is None: if is_start_per: freq = start.freq elif is_end_per: freq = end.freq else: # pragma: no cover raise ValueError("Could not infer freq from start/end") if periods is not None: periods = periods * mult if start is None: data = np.arange(end.ordinal - periods + mult, end.ordinal + 1, mult, dtype=np.int64) else: data = np.arange(start.ordinal, start.ordinal + periods, mult, dtype=np.int64) else: data = np.arange(start.ordinal, end.ordinal + 1, mult, dtype=np.int64) return data, freq
def _get_ordinal_range(start, end, periods, freq, mult=1): if com.count_not_none(start, end, periods) != 2: raise ValueError('Of the three parameters: start, end, and periods, ' 'exactly two must be specified') if freq is not None: _, mult = libfrequencies.get_freq_code(freq) if start is not None: start = Period(start, freq) if end is not None: end = Period(end, freq) is_start_per = isinstance(start, Period) is_end_per = isinstance(end, Period) if is_start_per and is_end_per and start.freq != end.freq: raise ValueError('start and end must have same freq') if (start is NaT or end is NaT): raise ValueError('start and end must not be NaT') if freq is None: if is_start_per: freq = start.freq elif is_end_per: freq = end.freq else: # pragma: no cover raise ValueError('Could not infer freq from start/end') if periods is not None: periods = periods * mult if start is None: data = np.arange(end.ordinal - periods + mult, end.ordinal + 1, mult, dtype=np.int64) else: data = np.arange(start.ordinal, start.ordinal + periods, mult, dtype=np.int64) else: data = np.arange(start.ordinal, end.ordinal + 1, mult, dtype=np.int64) return data, freq
def __init__( self, freq, minor_locator=False, dynamic_mode=True, base=1, quarter=1, month=1, day=1, plot_obj=None, ): if isinstance(freq, str): freq = get_freq_code(freq)[0] self.freq = freq self.base = base (self.quarter, self.month, self.day) = (quarter, month, day) self.isminor = minor_locator self.isdynamic = dynamic_mode self.offset = 0 self.plot_obj = plot_obj self.finder = get_finder(freq)
def get_freq_group(freq): """ Return frequency code group of given frequency str or offset. Example ------- >>> get_freq_group('W-MON') 4000 >>> get_freq_group('W-FRI') 4000 """ if isinstance(freq, offsets.DateOffset): freq = freq.rule_code if isinstance(freq, compat.string_types): base, mult = get_freq_code(freq) freq = base elif isinstance(freq, int): pass else: raise ValueError('input must be str, offset or int') return (freq // 1000) * 1000
def dt64arr_to_periodarr(data, freq, tz=None): """ Convert an datetime-like array to values Period ordinals. Parameters ---------- data : Union[Series[datetime64[ns]], DatetimeIndex, ndarray[datetime64ns]] freq : Optional[Union[str, Tick]] Must match the `freq` on the `data` if `data` is a DatetimeIndex or Series. tz : Optional[tzinfo] Returns ------- ordinals : ndarray[int] freq : Tick The frequencey extracted from the Series or DatetimeIndex if that's used. """ if data.dtype != np.dtype('M8[ns]'): raise ValueError('Wrong dtype: {dtype}'.format(dtype=data.dtype)) if freq is None: if isinstance(data, ABCIndexClass): data, freq = data._values, data.freq elif isinstance(data, ABCSeries): data, freq = data._values, data.dt.freq freq = Period._maybe_convert_freq(freq) if isinstance(data, (ABCIndexClass, ABCSeries)): data = data._values base, mult = libfrequencies.get_freq_code(freq) return libperiod.dt64arr_to_periodarr(data.view('i8'), base, tz), freq
def dt64arr_to_periodarr(data, freq, tz=None): """ Convert an datetime-like array to values Period ordinals. Parameters ---------- data : Union[Series[datetime64[ns]], DatetimeIndex, ndarray[datetime64ns]] freq : Optional[Union[str, Tick]] Must match the `freq` on the `data` if `data` is a DatetimeIndex or Series. tz : Optional[tzinfo] Returns ------- ordinals : ndarray[int] freq : Tick The frequency extracted from the Series or DatetimeIndex if that's used. """ if data.dtype != np.dtype("M8[ns]"): raise ValueError(f"Wrong dtype: {data.dtype}") if freq is None: if isinstance(data, ABCIndexClass): data, freq = data._values, data.freq elif isinstance(data, ABCSeries): data, freq = data._values, data.dt.freq freq = Period._maybe_convert_freq(freq) if isinstance(data, (ABCIndexClass, ABCSeries)): data = data._values base, mult = libfrequencies.get_freq_code(freq) return libperiod.dt64arr_to_periodarr(data.view("i8"), base, tz), freq
def test_period_ordinal_business_day(day, expected): args = (2013, 10, day, 0, 0, 0, 0, 0, get_freq_code("B")[0]) assert period_ordinal(*args) == expected
def test_get_to_timestamp_base(self): tsb = libfrequencies.get_to_timestamp_base assert (tsb(get_freq_code('D')[0]) == get_freq_code('D')[0]) assert (tsb(get_freq_code('W')[0]) == get_freq_code('D')[0]) assert (tsb(get_freq_code('M')[0]) == get_freq_code('D')[0]) assert (tsb(get_freq_code('S')[0]) == get_freq_code('S')[0]) assert (tsb(get_freq_code('T')[0]) == get_freq_code('S')[0]) assert (tsb(get_freq_code('H')[0]) == get_freq_code('S')[0])
def test_get_freq_code(self): # frequency str assert (get_freq_code('A') == (get_freq('A'), 1)) assert (get_freq_code('3D') == (get_freq('D'), 3)) assert (get_freq_code('-2M') == (get_freq('M'), -2)) # tuple assert (get_freq_code(('D', 1)) == (get_freq('D'), 1)) assert (get_freq_code(('A', 3)) == (get_freq('A'), 3)) assert (get_freq_code(('M', -2)) == (get_freq('M'), -2)) # numeric tuple assert get_freq_code((1000, 1)) == (1000, 1) # offsets assert (get_freq_code(offsets.Day()) == (get_freq('D'), 1)) assert (get_freq_code(offsets.Day(3)) == (get_freq('D'), 3)) assert (get_freq_code(offsets.Day(-2)) == (get_freq('D'), -2)) assert (get_freq_code(offsets.MonthEnd()) == (get_freq('M'), 1)) assert (get_freq_code(offsets.MonthEnd(3)) == (get_freq('M'), 3)) assert (get_freq_code(offsets.MonthEnd(-2)) == (get_freq('M'), -2)) assert (get_freq_code(offsets.Week()) == (get_freq('W'), 1)) assert (get_freq_code(offsets.Week(3)) == (get_freq('W'), 3)) assert (get_freq_code(offsets.Week(-2)) == (get_freq('W'), -2)) # Monday is weekday=0 assert (get_freq_code(offsets.Week(weekday=1)) == (get_freq('W-TUE'), 1)) assert (get_freq_code(offsets.Week(3, weekday=0)) == (get_freq('W-MON'), 3)) assert (get_freq_code(offsets.Week(-2, weekday=4)) == (get_freq('W-FRI'), -2))
def test_period_ordinal_start_values(freq, expected): # information for Jan. 1, 1970. assert period_ordinal(1970, 1, 1, 0, 0, 0, 0, 0, get_freq_code(freq)[0]) == expected
def test_period_ordinal_week(dt, expected): args = dt + (get_freq_code("W")[0], ) assert period_ordinal(*args) == expected
def test_get_code_invalid(): with pytest.raises(ValueError, match="Invalid frequency"): get_freq_code((5, "baz"))
def test_get_freq_code(freq_input, expected): assert get_freq_code(freq_input) == expected
def test_freq_code_match(period_code_item): freqstr, code = period_code_item assert get_freq_code(freqstr)[0] == code
def test_freq_code(freqstr, expected): assert get_freq_code(freqstr)[0] == expected
# Too much precision in the input can prevent. (0.3429324798798269273987982, "H"), ], ) def test_cat(args): msg = "Invalid frequency" with pytest.raises(ValueError, match=msg): to_offset(str(args[0]) + args[1]) @pytest.mark.parametrize( "freq_input,expected", [ # Frequency string. ("A", (get_freq_code("A")[0], 1)), ("3D", (get_freq_code("D")[0], 3)), ("-2M", (get_freq_code("M")[0], -2)), # Tuple. (("D", 1), (get_freq_code("D")[0], 1)), (("A", 3), (get_freq_code("A")[0], 3)), (("M", -2), (get_freq_code("M")[0], -2)), ((5, "T"), (FreqGroup.FR_MIN, 5)), # Numeric Tuple. ((1000, 1), (1000, 1)), # Offsets. (offsets.Day(), (get_freq_code("D")[0], 1)), (offsets.Day(3), (get_freq_code("D")[0], 3)), (offsets.Day(-2), (get_freq_code("D")[0], -2)), (offsets.MonthEnd(), (get_freq_code("M")[0], 1)), (offsets.MonthEnd(3), (get_freq_code("M")[0], 3)),
def test_get_to_timestamp_base(freqstr, exp_freqstr): tsb = libfrequencies.get_to_timestamp_base assert tsb(get_freq_code(freqstr)[0]) == get_freq_code(exp_freqstr)[0]
def f(self): base, mult = libfrequencies.get_freq_code(self.freq) result = get_period_field_arr(alias, self.asi8, base) return result
def test_intra_day_conversion_factors(freq1, freq2, expected): assert (period_asfreq(1, get_freq_code(freq1)[0], get_freq_code(freq2)[0], False) == expected)