def wrapper(self, other): if isinstance(other, Period): func = getattr(self._values, opname) other_base, _ = _gfc(other.freq) if other.freq != self.freq: msg = _DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) raise IncompatibleFrequency(msg) result = func(other.ordinal) elif isinstance(other, PeriodIndex): if other.freq != self.freq: msg = _DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) raise IncompatibleFrequency(msg) result = getattr(self._values, opname)(other._values) mask = self._isnan | other._isnan if mask.any(): result[mask] = nat_result return result elif other is tslib.NaT: result = np.empty(len(self._values), dtype=bool) result.fill(nat_result) else: other = Period(other, freq=self.freq) func = getattr(self._values, opname) result = func(other.ordinal) if self.hasnans: result[self._isnan] = nat_result return result
def _maybe_cast_slice_bound(self, label, side, kind): """ If label is a string or a datetime, cast it to Period.ordinal according to resolution. Parameters ---------- label : object side : {'left', 'right'} kind : {'ix', 'loc', 'getitem'} Returns ------- bound : Period or object Notes ----- Value of `side` parameter should be validated in caller. """ assert kind in ['ix', 'loc', 'getitem'] if isinstance(label, datetime): return Period(label, freq=self.freq) elif isinstance(label, compat.string_types): try: _, parsed, reso = parse_time_string(label, self.freq) bounds = self._parsed_string_to_bounds(reso, parsed) return bounds[0 if side == 'left' else 1] except Exception: raise KeyError(label) elif is_integer(label) or is_float(label): self._invalid_indexer('slice', label) return label
def get_loc(self, key, method=None, tolerance=None): """ Get integer location for requested label Returns ------- loc : int """ try: return self._engine.get_loc(key) except KeyError: if is_integer(key): raise try: asdt, parsed, reso = parse_time_string(key, self.freq) key = asdt except TypeError: pass try: key = Period(key, freq=self.freq) except ValueError: # we cannot construct the Period # as we have an invalid type raise KeyError(key) try: ordinal = tslib.iNaT if key is tslib.NaT else key.ordinal if tolerance is not None: tolerance = self._convert_tolerance(tolerance) return self._int64index.get_loc(ordinal, method, tolerance) except KeyError: raise KeyError(key)
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 = _gfc(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 tslib.NaT or end is tslib.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 _parsed_string_to_bounds(self, reso, parsed): if reso == 'year': t1 = Period(year=parsed.year, freq='A') elif reso == 'month': t1 = Period(year=parsed.year, month=parsed.month, freq='M') elif reso == 'quarter': q = (parsed.month - 1) // 3 + 1 t1 = Period(year=parsed.year, quarter=q, freq='Q-DEC') elif reso == 'day': t1 = Period(year=parsed.year, month=parsed.month, day=parsed.day, freq='D') elif reso == 'hour': t1 = Period(year=parsed.year, month=parsed.month, day=parsed.day, hour=parsed.hour, freq='H') elif reso == 'minute': t1 = Period(year=parsed.year, month=parsed.month, day=parsed.day, hour=parsed.hour, minute=parsed.minute, freq='T') elif reso == 'second': t1 = Period(year=parsed.year, month=parsed.month, day=parsed.day, hour=parsed.hour, minute=parsed.minute, second=parsed.second, freq='S') else: raise KeyError(reso) return (t1.asfreq(self.freq, how='start'), t1.asfreq(self.freq, how='end'))
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._values.searchsorted(value, side=side, sorter=sorter)
def get_value(self, series, key): """ Fast lookup of value from 1-dimensional ndarray. Only use this if you know what you're doing """ s = com._values_from_object(series) try: return com._maybe_box(self, super(PeriodIndex, self).get_value(s, key), series, key) except (KeyError, IndexError): try: asdt, parsed, reso = parse_time_string(key, self.freq) grp = resolution.Resolution.get_freq_group(reso) freqn = resolution.get_freq_group(self.freq) vals = self._values # if our data is higher resolution than requested key, slice if grp < freqn: iv = Period(asdt, freq=(grp, 1)) ord1 = iv.asfreq(self.freq, how='S').ordinal ord2 = iv.asfreq(self.freq, how='E').ordinal if ord2 < vals[0] or ord1 > vals[-1]: raise KeyError(key) pos = np.searchsorted(self._values, [ord1, ord2]) key = slice(pos[0], pos[1] + 1) return series[key] elif grp == freqn: key = Period(asdt, freq=self.freq).ordinal return com._maybe_box(self, self._engine.get_value(s, key), series, key) else: raise KeyError(key) except TypeError: pass key = Period(key, self.freq).ordinal return com._maybe_box(self, self._engine.get_value(s, key), series, key)