def _raise_on_incompatible(left, right): """ Helper function to render a consistent error message when raising IncompatibleFrequency. Parameters ---------- left : PeriodArray right : DateOffset, Period, ndarray, or timedelta-like Raises ------ IncompatibleFrequency """ # GH#24283 error message format depends on whether right is scalar if isinstance(right, np.ndarray): other_freq = None elif isinstance(right, (ABCPeriodIndex, PeriodArray, Period, DateOffset)): other_freq = right.freqstr else: other_freq = _delta_to_tick(Timedelta(right)).freqstr msg = DIFFERENT_FREQ.format(cls=type(left).__name__, own_freq=left.freqstr, other_freq=other_freq) raise IncompatibleFrequency(msg)
def raise_on_incompatible(left, right): """ Helper function to render a consistent error message when raising IncompatibleFrequency. Parameters ---------- left : PeriodArray right : None, DateOffset, Period, ndarray, or timedelta-like Returns ------- IncompatibleFrequency Exception to be raised by the caller. """ # GH#24283 error message format depends on whether right is scalar if isinstance(right, np.ndarray) or right is None: other_freq = None elif isinstance(right, (ABCPeriodIndex, PeriodArray, Period, DateOffset)): other_freq = right.freqstr else: other_freq = _delta_to_tick(Timedelta(right)).freqstr msg = DIFFERENT_FREQ.format(cls=type(left).__name__, own_freq=left.freqstr, other_freq=other_freq) return IncompatibleFrequency(msg)
def __init__(self, values, freq=None, dtype=None, copy=False): freq = validate_dtype_freq(dtype, freq) if freq is not None: freq = Period._maybe_convert_freq(freq) if isinstance(values, ABCSeries): values = values._values if not isinstance(values, type(self)): raise TypeError("Incorrect dtype") elif isinstance(values, ABCPeriodIndex): values = values._values if isinstance(values, type(self)): if freq is not None and freq != values.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=values.freq.freqstr, other_freq=freq.freqstr) raise IncompatibleFrequency(msg) values, freq = values._data, values.freq values = np.array(values, dtype='int64', copy=copy) self._data = values if freq is None: raise ValueError('freq is not specified and cannot be inferred') self._dtype = PeriodDtype(freq)
def __init__(self, values, freq=None, dtype=None, copy=False): freq = validate_dtype_freq(dtype, freq) if freq is not None: freq = Period._maybe_convert_freq(freq) if isinstance(values, ABCSeries): values = values._values if not isinstance(values, type(self)): raise TypeError("Incorrect dtype") elif isinstance(values, ABCPeriodIndex): values = values._values if isinstance(values, type(self)): if freq is not None and freq != values.freq: msg = DIFFERENT_FREQ.format( cls=type(self).__name__, own_freq=values.freq.freqstr, other_freq=freq.freqstr, ) raise IncompatibleFrequency(msg) values, freq = values._data, values.freq values = np.array(values, dtype="int64", copy=copy) self._data = values if freq is None: raise ValueError("freq is not specified and cannot be inferred") self._dtype = PeriodDtype(freq)
def _sub_period_array(self, other): """ Subtract a Period Array/Index from self. This is only valid if self is itself a Period Array/Index, raises otherwise. Both objects must have the same frequency. Parameters ---------- other : PeriodIndex or PeriodArray Returns ------- result : np.ndarray[object] Array of DateOffset objects; nulls represented by NaT. """ if self.freq != other.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=other.freqstr) raise IncompatibleFrequency(msg) new_values = algos.checked_add_with_arr(self.asi8, -other.asi8, arr_mask=self._isnan, b_mask=other._isnan) new_values = np.array([self.freq.base * x for x in new_values]) if self._hasnans or other._hasnans: mask = (self._isnan) | (other._isnan) new_values[mask] = NaT return new_values
def _maybe_convert_timedelta(self, other): """ Convert timedelta-like input to an integer multiple of self.freq Parameters ---------- other : timedelta, np.timedelta64, DateOffset, int, np.ndarray Returns ------- converted : int, np.ndarray[int64] Raises ------ IncompatibleFrequency : if the input cannot be written as a multiple of self.freq. Note IncompatibleFrequency subclasses ValueError. """ if isinstance( other, (timedelta, np.timedelta64, Tick, np.ndarray)): offset = frequencies.to_offset(self.freq.rule_code) if isinstance(offset, Tick): # _check_timedeltalike_freq_compat will raise if incompatible delta = self._data._check_timedeltalike_freq_compat(other) return delta elif isinstance(other, DateOffset): freqstr = other.rule_code base = frequencies.get_base_alias(freqstr) if base == self.freq.rule_code: return other.n msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=other.freqstr) raise IncompatibleFrequency(msg) elif is_integer(other): # integer is passed to .shift via # _add_datetimelike_methods basically # but ufunc may pass integer to _add_delta return other # raise when input doesn't have freq msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=None) raise IncompatibleFrequency(msg)
def _assert_can_do_setop(self, other): super()._assert_can_do_setop(other) # *Can't* use PeriodIndexes of different freqs # *Can* use PeriodIndex/DatetimeIndex if isinstance(other, PeriodIndex) and self.freq != other.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=other.freqstr) raise IncompatibleFrequency(msg)
def _assert_can_do_setop(self, other): super(PeriodIndex, self)._assert_can_do_setop(other) if not isinstance(other, PeriodIndex): raise ValueError('can only call with other PeriodIndex-ed objects') if self.freq != other.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=other.freqstr) raise IncompatibleFrequency(msg)
def _assert_can_do_setop(self, other): super()._assert_can_do_setop(other) if not isinstance(other, PeriodIndex): raise ValueError('can only call with other PeriodIndex-ed objects') if self.freq != other.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=other.freqstr) raise IncompatibleFrequency(msg)
def get_indexer_non_unique(self, target): target = ensure_index(target) if isinstance(target, PeriodIndex): target = target.asi8 if hasattr(target, "freq") and target.freq != self.freq: msg = DIFFERENT_FREQ.format( cls=type(self).__name__, own_freq=self.freqstr, other_freq=target.freqstr, ) raise IncompatibleFrequency(msg) indexer, missing = self._int64index.get_indexer_non_unique(target) return ensure_platform_int(indexer), missing
def get_indexer(self, target, method=None, limit=None, tolerance=None): target = ensure_index(target) if hasattr(target, 'freq') and target.freq != self.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=target.freqstr) raise IncompatibleFrequency(msg) if isinstance(target, PeriodIndex): target = target.asi8 if tolerance is not None: tolerance = self._convert_tolerance(tolerance, target) return Index.get_indexer(self._int64index, target, method, limit, tolerance)
def searchsorted(self, value, side='left', sorter=None): if isinstance(value, Period): if value.freq != self.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=value.freqstr) raise IncompatibleFrequency(msg) value = value.ordinal elif isinstance(value, compat.string_types): try: value = Period(value, freq=self.freq).ordinal except DateParseError: raise KeyError("Cannot interpret '{}' as period".format(value)) return self._ndarray_values.searchsorted(value, side=side, sorter=sorter)
def _require_matching_freq(self, other, base: bool = False) -> None: # See also arrays.period.raise_on_incompatible if isinstance(other, BaseOffset): other_freq = other else: other_freq = other.freq if base: condition = self.freq.base != other_freq.base else: condition = self.freq != other_freq if condition: msg = DIFFERENT_FREQ.format( cls=type(self).__name__, own_freq=self.freqstr, other_freq=other_freq.freqstr, ) raise IncompatibleFrequency(msg)
def _sub_period_array(self, other): """ Subtract a Period Array/Index from self. This is only valid if self is itself a Period Array/Index, raises otherwise. Both objects must have the same frequency. Parameters ---------- other : PeriodIndex or PeriodArray Returns ------- result : np.ndarray[object] Array of DateOffset objects; nulls represented by NaT """ if not is_period_dtype(self): raise TypeError("cannot subtract {dtype}-dtype from {cls}".format( dtype=other.dtype, cls=type(self).__name__)) if len(self) != len(other): raise ValueError("cannot subtract arrays/indices of " "unequal length") if self.freq != other.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=other.freqstr) raise IncompatibleFrequency(msg) new_values = checked_add_with_arr(self.asi8, -other.asi8, arr_mask=self._isnan, b_mask=other._isnan) new_values = np.array([self.freq.base * x for x in new_values]) if self._hasnans or other._hasnans: mask = (self._isnan) | (other._isnan) new_values[mask] = NaT return new_values
def _sub_period_array(self, other): """ Subtract a Period Array/Index from self. This is only valid if self is itself a Period Array/Index, raises otherwise. Both objects must have the same frequency. Parameters ---------- other : PeriodIndex or PeriodArray Returns ------- result : np.ndarray[object] Array of DateOffset objects; nulls represented by NaT """ if not is_period_dtype(self): raise TypeError("cannot subtract {dtype}-dtype from {cls}" .format(dtype=other.dtype, cls=type(self).__name__)) if len(self) != len(other): raise ValueError("cannot subtract arrays/indices of " "unequal length") if self.freq != other.freq: msg = DIFFERENT_FREQ.format(cls=type(self).__name__, own_freq=self.freqstr, other_freq=other.freqstr) raise IncompatibleFrequency(msg) new_values = checked_add_with_arr(self.asi8, -other.asi8, arr_mask=self._isnan, b_mask=other._isnan) new_values = np.array([self.freq.base * x for x in new_values]) if self.hasnans or other.hasnans: mask = (self._isnan) | (other._isnan) new_values[mask] = NaT return new_values