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
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)
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)
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
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
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
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
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)
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
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")
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
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)
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")
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
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
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)