Example #1
0
    def _validate_setitem_value(self, value):
        needs_float_conversion = False

        if is_valid_nat_for_dtype(value, self.left.dtype):
            # na value: need special casing to set directly on numpy arrays
            if is_integer_dtype(self.dtype.subtype):
                # can't set NaN on a numpy integer array
                needs_float_conversion = True
            elif is_datetime64_any_dtype(self.dtype.subtype):
                # need proper NaT to set directly on the numpy array
                value = np.datetime64("NaT")
            elif is_timedelta64_dtype(self.dtype.subtype):
                # need proper NaT to set directly on the numpy array
                value = np.timedelta64("NaT")
            value_left, value_right = value, value

        elif is_interval_dtype(value) or isinstance(value, Interval):
            # scalar interval
            self._check_closed_matches(value, name="value")
            value_left, value_right = value.left, value.right

        else:
            return self._validate_listlike(value)

        if needs_float_conversion:
            raise ValueError(
                "Cannot set float NaN to integer-backed IntervalArray")
        return value_left, value_right
Example #2
0
    def get_loc(self, key, method=None, tolerance=None):
        """
        Get integer location for requested label

        Returns
        -------
        loc : int, slice, or ndarray[int]
        """
        if not is_scalar(key):
            raise InvalidIndexError(key)

        if is_valid_nat_for_dtype(key, self.dtype):
            key = NaT

        elif isinstance(key, str):
            try:
                key = Timedelta(key)
            except ValueError:
                raise KeyError(key)

        elif isinstance(key, self._data._recognized_scalars) or key is NaT:
            key = Timedelta(key)

        else:
            raise KeyError(key)

        if tolerance is not None:
            # try converting tolerance now, so errors don't get swallowed by
            # the try/except clauses below
            tolerance = self._convert_tolerance(tolerance, np.asarray(key))

        return Index.get_loc(self, key, method, tolerance)
Example #3
0
    def get_loc(self, key, method=None, tolerance=None):
        """
        Get integer location for requested label

        Returns
        -------
        loc : int, slice, or ndarray[int]
        """
        if not is_scalar(key):
            raise InvalidIndexError(key)

        if is_valid_nat_for_dtype(key, self.dtype):
            key = NaT

        elif isinstance(key, str):
            try:
                key = Timedelta(key)
            except ValueError:
                raise KeyError(key)

        elif isinstance(key, self._data._recognized_scalars) or key is NaT:
            key = Timedelta(key)

        else:
            raise KeyError(key)

        return Index.get_loc(self, key, method, tolerance)
Example #4
0
    def _validate_fill_value(self, value):
        if is_bool(value) or is_bool_dtype(value):
            # force conversion to object
            # so we don't lose the bools
            raise TypeError
        elif is_scalar(value) and isna(value):
            if is_valid_nat_for_dtype(value, self.dtype):
                value = self._na_value
                if self.dtype.kind != "f":
                    # raise so that caller can cast
                    raise TypeError
            else:
                # NaT, np.datetime64("NaT"), np.timedelta64("NaT")
                raise TypeError

        elif is_scalar(value):
            if not is_number(value):
                # e.g. datetime64, timedelta64, datetime, ...
                raise TypeError

            elif lib.is_complex(value):
                # at least until we have a ComplexIndx
                raise TypeError

            elif is_float(value) and self.dtype.kind != "f":
                if not value.is_integer():
                    raise TypeError
                value = int(value)

        return value
Example #5
0
    def _validate_setitem_value(self, value):
        needs_float_conversion = False

        if is_valid_nat_for_dtype(value, self.left.dtype):
            # na value: need special casing to set directly on numpy arrays
            if is_integer_dtype(self.dtype.subtype):
                # can't set NaN on a numpy integer array
                needs_float_conversion = True
            elif is_datetime64_any_dtype(self.dtype.subtype):
                # need proper NaT to set directly on the numpy array
                value = np.datetime64("NaT")
            elif is_timedelta64_dtype(self.dtype.subtype):
                # need proper NaT to set directly on the numpy array
                value = np.timedelta64("NaT")
            value_left, value_right = value, value

        elif is_interval_dtype(value) or isinstance(value, Interval):
            # scalar interval
            self._check_closed_matches(value, name="value")
            value_left, value_right = value.left, value.right

        else:
            try:
                # list-like of intervals
                array = IntervalArray(value)
                value_left, value_right = array.left, array.right
            except TypeError as err:
                # wrong type: not interval or NA
                msg = f"'value' should be an interval type, got {type(value)} instead."
                raise TypeError(msg) from err

        if needs_float_conversion:
            raise ValueError(
                "Cannot set float NaN to integer-backed IntervalArray")
        return value_left, value_right
Example #6
0
    def _validate_fill_value(self, value):
        if is_bool(value) or is_bool_dtype(value):
            # force conversion to object
            # so we don't lose the bools
            raise TypeError
        elif is_scalar(value) and isna(value):
            if is_valid_nat_for_dtype(value, self.dtype):
                value = self._na_value
                if self.dtype.kind != "f":
                    # raise so that caller can cast
                    raise TypeError
            else:
                # NaT, np.datetime64("NaT"), np.timedelta64("NaT")
                raise TypeError

        elif is_scalar(value):
            if not is_number(value):
                # e.g. datetime64, timedelta64, datetime, ...
                raise TypeError

            elif lib.is_complex(value):
                # at least until we have a ComplexIndx
                raise TypeError

            elif is_float(value) and self.dtype.kind != "f":
                if not value.is_integer():
                    raise TypeError
                value = int(value)

        elif hasattr(value, "dtype") and value.dtype.kind in ["m", "M"]:
            # TODO: if we're checking arraylike here, do so systematically
            raise TypeError

        return value
Example #7
0
    def insert(self, loc, item):
        """
        Make new Index inserting new item at location

        Parameters
        ----------
        loc : int
        item : object
            if not either a Python datetime or a numpy integer-like, returned
            Index dtype will be object rather than datetime.

        Returns
        -------
        new_index : Index
        """
        if isinstance(item, self._data._recognized_scalars):
            item = self._data._scalar_type(item)
        elif is_valid_nat_for_dtype(item, self.dtype):
            # GH 18295
            item = self._na_value
        elif is_scalar(item) and isna(item):
            raise TypeError(
                f"cannot insert {type(self).__name__} with incompatible label")

        freq = None
        if isinstance(item, self._data._scalar_type) or item is NaT:
            self._data._check_compatible_with(item, setitem=True)

            # check freq can be preserved on edge cases
            if self.size and self.freq is not None:
                if item is NaT:
                    pass
                elif (loc == 0
                      or loc == -len(self)) and item + self.freq == self[0]:
                    freq = self.freq
                elif (loc == len(self)) and item - self.freq == self[-1]:
                    freq = self.freq
            elif self.freq is not None:
                # Adding a single item to an empty index may preserve freq
                if self.freq.is_on_offset(item):
                    freq = self.freq
            item = item.asm8

        try:
            new_i8s = np.concatenate(
                (self[:loc].asi8, [item.view(np.int64)], self[loc:].asi8))
            arr = type(self._data)._simple_new(new_i8s,
                                               dtype=self.dtype,
                                               freq=freq)
            return type(self)._simple_new(arr, name=self.name)
        except (AttributeError, TypeError) as err:

            # fall back to object index
            if isinstance(item, str):
                return self.astype(object).insert(loc, item)
            raise TypeError(
                f"cannot insert {type(self).__name__} with incompatible label"
            ) from err
Example #8
0
    def insert(self, loc: int, item):
        # treat NA values as nans:
        if is_scalar(item) and isna(item):
            if is_valid_nat_for_dtype(item, self.dtype):
                item = self._na_value
            else:
                # NaT, np.datetime64("NaT"), np.timedelta64("NaT")
                return self.astype(object).insert(loc, item)

        return super().insert(loc, item)
Example #9
0
 def _validate_scalar(self, value):
     if isinstance(value, Interval):
         self._check_closed_matches(value, name="value")
         left, right = value.left, value.right
     elif is_valid_nat_for_dtype(value, self.left.dtype):
         # GH#18295
         left = right = value
     else:
         raise TypeError(
             "can only insert Interval objects and NA into an IntervalArray"
         )
     return left, right
Example #10
0
    def insert(self, loc, item):
        """
        Make new Index inserting new item at location

        Parameters
        ----------
        loc : int
        item : object
            if not either a Python datetime or a numpy integer-like, returned
            Index dtype will be object rather than datetime.

        Returns
        -------
        new_index : Index
        """
        if is_valid_nat_for_dtype(item, self.dtype):
            # GH 18295
            item = self._na_value
        elif is_scalar(item) and isna(item):
            # i.e. timedeltat64("NaT")
            raise TypeError(
                f"cannot insert {type(self).__name__} with incompatible label")

        freq = None

        if isinstance(item, (datetime, np.datetime64)):
            self._assert_can_do_op(item)
            if not self._has_same_tz(item) and not isna(item):
                raise ValueError(
                    "Passed item and index have different timezone")

            # check freq can be preserved on edge cases
            if self.size and self.freq is not None:
                if item is NaT:
                    pass
                elif (loc == 0
                      or loc == -len(self)) and item + self.freq == self[0]:
                    freq = self.freq
                elif (loc == len(self)) and item - self.freq == self[-1]:
                    freq = self.freq
            item = _to_M8(item, tz=self.tz)

        try:
            new_dates = np.concatenate(
                (self[:loc].asi8, [item.view(np.int64)], self[loc:].asi8))
            return self._shallow_copy(new_dates, freq=freq)
        except (AttributeError, TypeError):

            # fall back to object index
            if isinstance(item, str):
                return self.astype(object).insert(loc, item)
            raise TypeError(
                "cannot insert DatetimeIndex with incompatible label")
Example #11
0
    def get_loc(self, key, method=None, tolerance=None):
        """
        Get integer location for requested label

        Returns
        -------
        loc : int
        """
        if not is_scalar(key):
            raise InvalidIndexError(key)

        orig_key = key
        if is_valid_nat_for_dtype(key, self.dtype):
            key = NaT

        if isinstance(key, self._data._recognized_scalars):
            # needed to localize naive datetimes
            self._deprecate_mismatched_indexing(key)
            key = self._maybe_cast_for_get_loc(key)

        elif isinstance(key, str):
            try:
                return self._get_string_slice(key)
            except (TypeError, KeyError, ValueError, OverflowError):
                pass

            try:
                key = self._maybe_cast_for_get_loc(key)
            except ValueError as err:
                raise KeyError(key) from err

        elif isinstance(key, timedelta):
            # GH#20464
            raise TypeError(
                f"Cannot index {type(self).__name__} with {type(key).__name__}"
            )

        elif isinstance(key, time):
            if method is not None:
                raise NotImplementedError(
                    "cannot yet lookup inexact labels when key is a time object"
                )
            return self.indexer_at_time(key)

        else:
            # unrecognized type
            raise KeyError(key)

        try:
            return Index.get_loc(self, key, method, tolerance)
        except KeyError as err:
            raise KeyError(orig_key) from err
Example #12
0
    def get_loc(self, key, method=None, tolerance=None):
        """
        Get integer location for requested label

        Returns
        -------
        loc : int
        """
        if not is_scalar(key):
            raise InvalidIndexError(key)

        if is_valid_nat_for_dtype(key, self.dtype):
            key = NaT

        if tolerance is not None:
            # try converting tolerance now, so errors don't get swallowed by
            # the try/except clauses below
            tolerance = self._convert_tolerance(tolerance, np.asarray(key))

        if isinstance(key, (datetime, np.datetime64)):
            # needed to localize naive datetimes
            key = self._maybe_cast_for_get_loc(key)
            return Index.get_loc(self, key, method, tolerance)

        elif isinstance(key, str):
            try:
                return self._get_string_slice(key)
            except (TypeError, KeyError, ValueError, OverflowError):
                pass

            try:
                stamp = self._maybe_cast_for_get_loc(key)
                return Index.get_loc(self, stamp, method, tolerance)
            except (KeyError, ValueError):
                raise KeyError(key)

        elif isinstance(key, timedelta):
            # GH#20464
            raise TypeError(
                f"Cannot index {type(self).__name__} with {type(key).__name__}"
            )

        if isinstance(key, time):
            if method is not None:
                raise NotImplementedError(
                    "cannot yet lookup inexact labels when key is a time object"
                )
            return self.indexer_at_time(key)

        return Index.get_loc(self, key, method, tolerance)
Example #13
0
    def insert(self, loc, item):
        """
        Make new Index inserting new item at location

        Parameters
        ----------
        loc : int
        item : object
            If not either a Python datetime or a numpy integer-like, returned
            Index dtype will be object rather than datetime.

        Returns
        -------
        new_index : Index
        """
        # try to convert if possible
        if isinstance(item, self._data._recognized_scalars):
            item = Timedelta(item)
        elif is_valid_nat_for_dtype(item, self.dtype):
            # GH 18295
            item = self._na_value
        elif is_scalar(item) and isna(item):
            # i.e. datetime64("NaT")
            raise TypeError(
                f"cannot insert {type(self).__name__} with incompatible label")

        freq = None
        if isinstance(item, Timedelta) or (is_scalar(item) and isna(item)):

            # check freq can be preserved on edge cases
            if self.freq is not None:
                if (loc == 0
                        or loc == -len(self)) and item + self.freq == self[0]:
                    freq = self.freq
                elif (loc == len(self)) and item - self.freq == self[-1]:
                    freq = self.freq
            item = Timedelta(item).asm8.view(_TD_DTYPE)

        try:
            new_tds = np.concatenate(
                (self[:loc].asi8, [item.view(np.int64)], self[loc:].asi8))
            return self._shallow_copy(new_tds, freq=freq)

        except (AttributeError, TypeError):

            # fall back to object index
            if isinstance(item, str):
                return self.astype(object).insert(loc, item)
            raise TypeError(
                "cannot insert TimedeltaIndex with incompatible label")
Example #14
0
 def _validate_insert_value(self, value):
     if isinstance(value, Interval):
         if value.closed != self.closed:
             raise ValueError(
                 "inserted item must be closed on the same side as the index"
             )
         left_insert = value.left
         right_insert = value.right
     elif is_valid_nat_for_dtype(value, self.left.dtype):
         # GH#18295
         left_insert = right_insert = value
     else:
         raise ValueError(
             "can only insert Interval objects and NA into an IntervalIndex"
         )
     return left_insert, right_insert
Example #15
0
    def _validate_fill_value(self, value):
        """
        Convert value to be insertable to ndarray.
        """
        if is_bool(value) or is_bool_dtype(value):
            # force conversion to object
            # so we don't lose the bools
            raise TypeError
        elif isinstance(value, str) or lib.is_complex(value):
            raise TypeError
        elif is_scalar(value) and isna(value):
            if is_valid_nat_for_dtype(value, self.dtype):
                value = self._na_value
            else:
                # NaT, np.datetime64("NaT"), np.timedelta64("NaT")
                raise TypeError

        return value
Example #16
0
    def __contains__(self, key: Any) -> bool:
        # if key is a NaN, check if any NaN is in self.
        if is_valid_nat_for_dtype(key, self.categories.dtype):
            return self.hasnans

        return contains(self, key, container=self._engine)