Ejemplo n.º 1
0
    def wrapper(self, other):
        op = getattr(self._ndarray_values, opname)
        if isinstance(other, Period):
            if other.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
                raise IncompatibleFrequency(msg)

            result = op(other.ordinal)
        elif isinstance(other, PeriodArrayMixin):
            if other.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
                raise IncompatibleFrequency(msg)

            result = op(other._ndarray_values)

            mask = self._isnan | other._isnan
            if mask.any():
                result[mask] = nat_result

            return result
        elif other is NaT:
            result = np.empty(len(self._ndarray_values), dtype=bool)
            result.fill(nat_result)
        else:
            other = Period(other, freq=self.freq)
            result = op(other.ordinal)

        if self.hasnans:
            result[self._isnan] = nat_result

        return result
Ejemplo n.º 2
0
    def wrapper(self, other):
        op = getattr(self._ndarray_values, opname)
        if isinstance(other, Period):
            if other.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
                raise IncompatibleFrequency(msg)

            result = op(other.ordinal)
        elif isinstance(other, PeriodArrayMixin):
            if other.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
                raise IncompatibleFrequency(msg)

            result = op(other._ndarray_values)

            mask = self._isnan | other._isnan
            if mask.any():
                result[mask] = nat_result

            return result
        elif other is NaT:
            result = np.empty(len(self._ndarray_values), dtype=bool)
            result.fill(nat_result)
        else:
            other = Period(other, freq=self.freq)
            result = op(other.ordinal)

        if self.hasnans:
            result[self._isnan] = nat_result

        return result
Ejemplo n.º 3
0
 def _add_offset(self, other):
     assert not isinstance(other, Tick)
     base = frequencies.get_base_alias(other.rule_code)
     if base != self.freq.rule_code:
         msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
         raise IncompatibleFrequency(msg)
     return self.shift(other.n)
Ejemplo n.º 4
0
 def _add_offset(self, other):
     assert not isinstance(other, Tick)
     base = frequencies.get_base_alias(other.rule_code)
     if base != self.freq.rule_code:
         msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
         raise IncompatibleFrequency(msg)
     return self.shift(other.n)
Ejemplo n.º 5
0
 def _maybe_convert_timedelta(self, other):
     if isinstance(other, (timedelta, np.timedelta64, Tick, np.ndarray)):
         offset = frequencies.to_offset(self.freq.rule_code)
         if isinstance(offset, Tick):
             if isinstance(other, np.ndarray):
                 nanos = np.vectorize(delta_to_nanoseconds)(other)
             else:
                 nanos = delta_to_nanoseconds(other)
             offset_nanos = delta_to_nanoseconds(offset)
             check = np.all(nanos % offset_nanos == 0)
             if check:
                 return nanos // offset_nanos
     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_INDEX.format(self.freqstr, 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 = "Input has different freq from PeriodIndex(freq={0})"
     raise IncompatibleFrequency(msg.format(self.freqstr))
Ejemplo n.º 6
0
    def _sub_period_array(self, other):
        """
        Subtract one PeriodIndex from another.  This is only valid if they
        have the same frequency.

        Parameters
        ----------
        other : PeriodIndex

        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 to {cls}".format(
                dtype=other.dtype, cls=type(self).__name__))

        if not len(self) == len(other):
            raise ValueError("cannot subtract indices of unequal length")
        if self.freq != other.freq:
            msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, 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 * x for x in new_values])
        if self.hasnans or other.hasnans:
            mask = (self._isnan) | (other._isnan)
            new_values[mask] = NaT
        return new_values
Ejemplo n.º 7
0
    def __init__(self, values, freq=None, dtype=None, copy=False):
        freq = dtl.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_INDEX.format(values.freq.freqstr,
                                                  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)
Ejemplo n.º 8
0
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: %s' % data.dtype)

    if freq is not None:
        freq = Period._maybe_convert_freq(freq)

    if isinstance(data, ABCIndexClass):
        if freq is None:
            freq = data.freq
        elif freq != data.freq:
            msg = DIFFERENT_FREQ_INDEX.format(freq.freqstr, data.freq.freqstr)
            raise IncompatibleFrequency(msg)
        data = data._values

    elif isinstance(data, ABCSeries):
        if freq is None:
            freq = data.dt.freq
        elif freq != data.dt.freq:
            msg = DIFFERENT_FREQ_INDEX.format(freq.freqstr,
                                              data.dt.freq.freqstr)
            raise IncompatibleFrequency(msg)
        data = data._values

    base, mult = frequencies.get_freq_code(freq)
    return libperiod.dt64arr_to_periodarr(data.view('i8'), base, tz), freq
Ejemplo n.º 9
0
    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_INDEX.format(self.freqstr, other.freqstr)
            raise IncompatibleFrequency(msg)
Ejemplo n.º 10
0
    def __setitem__(
            self,
            key,   # type: Union[int, Sequence[int], Sequence[bool], slice]
            value  # type: Union[NaTType, Period, Sequence[Period]]
    ):
        # type: (...) -> None
        # n.b. the type on `value` is a bit too restrictive.
        # we also accept a sequence of stuff coercible to a PeriodArray
        # by period_array, which includes things like ndarray[object],
        # ndarray[datetime64ns]. I think ndarray[int] / ndarray[str] won't
        # work, since the freq can't be inferred.
        if is_list_like(value):
            is_slice = isinstance(key, slice)
            if (not is_slice
                    and len(key) != len(value)
                    and not com.is_bool_indexer(key)):
                msg = ("shape mismatch: value array of length '{}' does not "
                       "match indexing result of length '{}'.")
                raise ValueError(msg.format(len(key), len(value)))
            if not is_slice and len(key) == 0:
                return

            value = period_array(value)

            if self.freqstr != value.freqstr:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, value.freqstr)
                raise IncompatibleFrequency(msg)

            value = value.asi8
        elif isinstance(value, Period):

            if self.freqstr != value.freqstr:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, value.freqstr)
                raise IncompatibleFrequency(msg)

            value = value.ordinal
        elif isna(value):
            value = iNaT
        else:
            msg = ("'value' should be a 'Period', 'NaT', or array of those. "
                   "Got '{}' instead.".format(type(value).__name__))
            raise TypeError(msg)
        self._data[key] = value
Ejemplo n.º 11
0
    def __setitem__(
            self,
            key,   # type: Union[int, Sequence[int], Sequence[bool], slice]
            value  # type: Union[NaTType, Period, Sequence[Period]]
    ):
        # type: (...) -> None
        # n.b. the type on `value` is a bit too restrictive.
        # we also accept a sequence of stuff coercible to a PeriodArray
        # by period_array, which includes things like ndarray[object],
        # ndarray[datetime64ns]. I think ndarray[int] / ndarray[str] won't
        # work, since the freq can't be inferred.
        if is_list_like(value):
            is_slice = isinstance(key, slice)
            if (not is_slice
                    and len(key) != len(value)
                    and not com.is_bool_indexer(key)):
                msg = ("shape mismatch: value array of length '{}' does not "
                       "match indexing result of length '{}'.")
                raise ValueError(msg.format(len(key), len(value)))
            if not is_slice and len(key) == 0:
                return

            value = period_array(value)

            if self.freqstr != value.freqstr:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, value.freqstr)
                raise IncompatibleFrequency(msg)

            value = value.asi8
        elif isinstance(value, Period):

            if self.freqstr != value.freqstr:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, value.freqstr)
                raise IncompatibleFrequency(msg)

            value = value.ordinal
        elif isna(value):
            value = iNaT
        else:
            msg = ("'value' should be a 'Period', 'NaT', or array of those. "
                   "Got '{}' instead.".format(type(value).__name__))
            raise TypeError(msg)
        self._data[key] = value
Ejemplo n.º 12
0
    def searchsorted(self, value, side='left', sorter=None):
        if isinstance(value, Period):
            if value.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, value.freqstr)
                raise IncompatibleFrequency(msg)
            value = value.ordinal
        elif isinstance(value, compat.string_types):
            value = Period(value, freq=self.freq).ordinal

        return self._ndarray_values.searchsorted(value, side=side,
                                                 sorter=sorter)
Ejemplo n.º 13
0
    def searchsorted(self, value, side='left', sorter=None):
        if isinstance(value, Period):
            if value.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, value.freqstr)
                raise IncompatibleFrequency(msg)
            value = value.ordinal
        elif isinstance(value, compat.string_types):
            value = Period(value, freq=self.freq).ordinal

        return self._ndarray_values.searchsorted(value, side=side,
                                                 sorter=sorter)
Ejemplo n.º 14
0
    def wrapper(self, other):
        op = getattr(self.asi8, opname)
        # We want to eventually defer to the Series or PeriodIndex (which will
        # return here with an unboxed PeriodArray). But before we do that,
        # we do a bit of validation on type (Period) and freq, so that our
        # error messages are sensible
        not_implemented = isinstance(other, (ABCSeries, ABCIndexClass))
        if not_implemented:
            other = other._values

        if isinstance(other, Period):
            if other.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
                raise IncompatibleFrequency(msg)

            result = op(other.ordinal)
        elif isinstance(other, cls):
            if other.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
                raise IncompatibleFrequency(msg)

            if not_implemented:
                return NotImplemented
            result = op(other.asi8)

            mask = self._isnan | other._isnan
            if mask.any():
                result[mask] = nat_result

            return result
        elif other is NaT:
            result = np.empty(len(self.asi8), dtype=bool)
            result.fill(nat_result)
        else:
            other = Period(other, freq=self.freq)
            result = op(other.ordinal)

        if self.hasnans:
            result[self._isnan] = nat_result

        return result
Ejemplo n.º 15
0
    def _add_offset(self, other):
        assert not isinstance(other, Tick)
        base = frequencies.get_base_alias(other.rule_code)
        if base != self.freq.rule_code:
            msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
            raise IncompatibleFrequency(msg)

        # Note: when calling parent class's _add_timedeltalike_scalar,
        #  it will call delta_to_nanoseconds(delta).  Because delta here
        #  is an integer, delta_to_nanoseconds will return it unchanged.
        result = super(PeriodArray, self)._add_timedeltalike_scalar(other.n)
        return type(self)(result, freq=self.freq)
Ejemplo n.º 16
0
 def _validate_fill_value(self, fill_value):
     if isna(fill_value):
         fill_value = iNaT
     elif isinstance(fill_value, Period):
         if fill_value.freq != self.freq:
             msg = DIFFERENT_FREQ_INDEX.format(self.freq.freqstr,
                                               fill_value.freqstr)
             raise IncompatibleFrequency(msg)
         fill_value = fill_value.ordinal
     else:
         raise ValueError("'fill_value' should be a Period. "
                          "Got '{got}'.".format(got=fill_value))
     return fill_value
Ejemplo n.º 17
0
 def _validate_fill_value(self, fill_value):
     if isna(fill_value):
         fill_value = iNaT
     elif isinstance(fill_value, Period):
         if fill_value.freq != self.freq:
             msg = DIFFERENT_FREQ_INDEX.format(self.freq.freqstr,
                                               fill_value.freqstr)
             raise IncompatibleFrequency(msg)
         fill_value = fill_value.ordinal
     else:
         raise ValueError("'fill_value' should be a Period. "
                          "Got '{got}'.".format(got=fill_value))
     return fill_value
Ejemplo n.º 18
0
    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_INDEX.format(self.freqstr, 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)
Ejemplo n.º 19
0
    def searchsorted(self, value, side='left', sorter=None):
        if isinstance(value, Period):
            if value.freq != self.freq:
                msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, 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)
Ejemplo n.º 20
0
    def _sub_period(self, other):
        # If the operation is well-defined, we return an object-Index
        # of DateOffsets.  Null entries are filled with pd.NaT
        if self.freq != other.freq:
            msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
            raise IncompatibleFrequency(msg)

        asi8 = self.asi8
        new_data = asi8 - other.ordinal
        new_data = np.array([self.freq * x for x in new_data])

        if self.hasnans:
            new_data[self._isnan] = NaT

        return new_data
Ejemplo n.º 21
0
    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):
                if isinstance(other, np.ndarray):
                    nanos = np.vectorize(delta_to_nanoseconds)(other)
                else:
                    nanos = delta_to_nanoseconds(other)
                offset_nanos = delta_to_nanoseconds(offset)
                check = np.all(nanos % offset_nanos == 0)
                if check:
                    return nanos // offset_nanos
        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_INDEX.format(self.freqstr, other.freqstr)
            raise IncompatibleFrequency(msg)
        elif lib.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 = "Input has different freq from {cls}(freq={freqstr})"
        raise IncompatibleFrequency(msg.format(cls=type(self).__name__,
                                               freqstr=self.freqstr))
Ejemplo n.º 22
0
    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):
                if isinstance(other, np.ndarray):
                    nanos = np.vectorize(delta_to_nanoseconds)(other)
                else:
                    nanos = delta_to_nanoseconds(other)
                offset_nanos = delta_to_nanoseconds(offset)
                check = np.all(nanos % offset_nanos == 0)
                if check:
                    return nanos // offset_nanos
        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_INDEX.format(self.freqstr, other.freqstr)
            raise IncompatibleFrequency(msg)
        elif lib.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 = "Input has different freq from {cls}(freq={freqstr})"
        raise IncompatibleFrequency(msg.format(cls=type(self).__name__,
                                               freqstr=self.freqstr))
Ejemplo n.º 23
0
    def take(self, indices, allow_fill=False, fill_value=None):
        if allow_fill:
            if isna(fill_value):
                fill_value = iNaT
            elif isinstance(fill_value, Period):
                if self.freq != fill_value.freq:
                    msg = DIFFERENT_FREQ_INDEX.format(self.freq.freqstr,
                                                      fill_value.freqstr)
                    raise IncompatibleFrequency(msg)

                fill_value = fill_value.ordinal
            else:
                msg = "'fill_value' should be a Period. Got '{}'."
                raise ValueError(msg.format(fill_value))

        new_values = algos.take(self._data,
                                indices,
                                allow_fill=allow_fill,
                                fill_value=fill_value)

        return type(self)(new_values, self.freq)
Ejemplo n.º 24
0
    def take(self, indices, allow_fill=False, fill_value=None):
        if allow_fill:
            if isna(fill_value):
                fill_value = iNaT
            elif isinstance(fill_value, Period):
                if self.freq != fill_value.freq:
                    msg = DIFFERENT_FREQ_INDEX.format(
                        self.freq.freqstr,
                        fill_value.freqstr
                    )
                    raise IncompatibleFrequency(msg)

                fill_value = fill_value.ordinal
            else:
                msg = "'fill_value' should be a Period. Got '{}'."
                raise ValueError(msg.format(fill_value))

        new_values = algos.take(self._data,
                                indices,
                                allow_fill=allow_fill,
                                fill_value=fill_value)

        return type(self)(new_values, self.freq)
Ejemplo n.º 25
0
    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 to {cls}"
                            .format(dtype=other.dtype,
                                    cls=type(self).__name__))

        if not len(self) == len(other):
            raise ValueError("cannot subtract arrays/indices of "
                             "unequal length")
        if self.freq != other.freq:
            msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, 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 * x for x in new_values])
        if self.hasnans or other.hasnans:
            mask = (self._isnan) | (other._isnan)
            new_values[mask] = NaT
        return new_values
Ejemplo n.º 26
0
 def _check_compatible_with(self, other):
     if self.freqstr != other.freqstr:
         msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
         raise IncompatibleFrequency(msg)
Ejemplo n.º 27
0
 def _check_compatible_with(self, other):
     if self.freqstr != other.freqstr:
         msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr)
         raise IncompatibleFrequency(msg)