def date_array(dlist=None, start_date=None, end_date=None, length=None, freq=None): """Constructs a DateArray from: - a starting date and either an ending date or a given length. - a list of dates. """ freq = check_freq(freq) # Case #1: we have a list ................... if dlist is not None: # Already a DateArray.................... if isinstance(dlist, DateArray): if (freq != _c.FR_UND) and (dlist.freq != check_freq(freq)): return dlist.asfreq(freq) else: return dlist # Make sure it's a sequence, else that's a start_date if hasattr(dlist,'__len__'): return _listparser(dlist, freq) elif start_date is not None: if end_date is not None: dmsg = "What starting date should be used ? '%s' or '%s' ?" raise DateError, dmsg % (dlist, start_date) else: (start_date, end_date) = (dlist, start_date) else: start_date = dlist # Case #2: we have a starting date .......... if start_date is None: if length == 0: return DateArray([], freq=freq) raise InsufficientDateError if not isDate(start_date): dmsg = "Starting date should be a valid Date instance! " dmsg += "(got '%s' instead)" % type(start_date) raise DateError, dmsg # Check if we have an end_date if end_date is None: if length is None: # raise ValueError,"No length precised!" length = 1 else: if not isDate(end_date): raise DateError, "Ending date should be a valid Date instance!" length = int(end_date - start_date) + 1 # dlist = [(start_date+i).value for i in range(length)] dlist = numeric.arange(length, dtype=int_) dlist += start_date.value if freq == _c.FR_UND: freq = start_date.freq return DateArray(dlist, freq=freq)
def fill_missing_dates(dates, freq=None): """ Finds and fills the missing dates in a :class:`DateArray`. Parameters ---------- dates : {DateArray} Initial array of dates. freq : {freq_spec}, optional Frequency of result. If not specified, the frequency of the input is used. """ # Check the frequency ........ orig_freq = freq freq = check_freq(freq) if (orig_freq is not None) and (freq == _c.FR_UND): freqstr = check_freq_str(freq) errmsg = "Unable to define a proper date resolution (found %s)." raise ValueError(errmsg % freqstr) # Check the dates ............. if not isinstance(dates, DateArray): errmsg = "A DateArray was expected, got %s instead." raise ValueError(errmsg % type(dates)) # Convert the dates to the new frequency (if needed) if freq != dates.freq: dates = dates.asfreq(freq) # Flatten the array if dates.ndim != 1: dates = dates.ravel() # Skip if there's no need to fill if not dates.has_missing_dates(): return dates # ...and now, fill it ! ...... (tstart, tend) = dates[[0, -1]] return date_array(start_date=tstart, end_date=tend)
def __new__(cls, dates=None, unit=None, freq=None, copy=False, timestep=None): # if unit is None: unit = freq # Get the frequency ...... if unit is None: _unit = getattr(dates, 'unit', _c.FR_UND) else: _unit = check_freq(unit) # Get the timestep _timestep = timestep or 1 # Get the dates .......... _dates = np.array(dates, copy=copy, dtype=int, subok=1) if _dates.ndim == 0: _dates.shape = (1,) _dates = _dates.view(cls) _dates._unit = _unit _dates._timestep = _timestep # _cached = _dates._cachedinfo if _cached['ischrono'] is None: sortidx = _dates.__array__().ravel().argsort() sortflag = (sortidx == np.arange(_dates.size)).all() if sortflag: _cached['chronidx'] = None else: _cached['chronidx'] = sortidx _cached['ischrono'] = sortflag return _dates
def asfreq(self, freq=None, relation="AFTER"): "Converts the dates to another frequency." # Note: As we define a new object, we don't need caching if freq is None or freq == _c.FR_UND: return self tofreq = check_freq(freq) if tofreq == self.freq: return self _rel = relation.upper()[0] fromfreq = self.freq if fromfreq == _c.FR_UND: fromfreq = _c.FR_DAY new = cseries.DA_asfreq(numeric.asarray(self), fromfreq, tofreq, _rel) return DateArray(new, freq=freq)
def __new__(cls, dates=None, freq=None, copy=False): # Get the frequency ...... if freq is None: _freq = getattr(dates, 'freq', _c.FR_UND) else: _freq = check_freq(freq) # Get the dates .......... _dates = numeric.array(dates, copy=copy, dtype=int_, subok=1) if _dates.ndim == 0: _dates.shape = (1,) _dates = _dates.view(cls) _dates.freq = _freq _dates._unsorted = None return _dates
def asunit(self, unit=None, relation="END", freq=None): """ Converts the dates to another frequency. Parameters ---------- unit : {freq_spec} Frequency into which :class:`DateArray` must be converted. Accepts any valid frequency specification (string or integer) relation : {"END", "START"} (optional) Applies only when converting a lower frequency :class:`Date` to a higher frequency :class:`Date`, or when converting a weekend :class:`Date` to a business frequency :class:`Date`. Valid values are 'START' and 'END' (or just 'S' and 'E' for brevity if you wish). For example, if converting a monthly date to a daily date, specifying 'START' ('END') would result in the first (last) day in the month. """ if unit is None: unit = freq # Note: As we define a new object, we don't need caching if (unit is None) or (unit == _c.FR_UND): return self tounit = check_freq(unit) if tounit == self._unit: return self relation = relation.upper() if relation not in ('START', 'END', 'S', 'E'): errmsg = "Invalid specification for the 'relation' parameter: %s" raise ValueError(errmsg % relation) fromunit = self._unit if fromunit == _c.FR_UND: new = self.__array__() else: new = cseries.DateArray_asfreq(self.__array__(), fromunit, tounit, relation[0]) return DateArray(new, unit=unit)
def __new__(cls, dates=None, freq=None, copy=False): # Get the frequency ...... if freq is None: _freq = getattr(dates, 'freq', _c.FR_UND) else: _freq = check_freq(freq) # Get the dates .......... _dates = np.array(dates, copy=copy, dtype=int, subok=1) if _dates.ndim == 0: _dates.shape = (1,) _dates = _dates.view(cls) _dates.freq = _freq # _cached = _dates._cachedinfo if _cached['ischrono'] is None: sortidx = _dates.__array__().ravel().argsort() sortflag = (sortidx == np.arange(_dates.size)).all() if sortflag: _cached['chronidx'] = None else: _cached['chronidx'] = sortidx _cached['ischrono'] = sortflag return _dates
def __new__(cls, dates=None, freq=None, copy=False): # Get the frequency ...... if freq is None: _freq = getattr(dates, 'freq', _c.FR_UND) else: _freq = check_freq(freq) # Get the dates .......... _dates = np.array(dates, copy=copy, dtype=int, subok=1) if _dates.ndim == 0: _dates.shape = (1, ) _dates = _dates.view(cls) _dates.freq = _freq # _cached = _dates._cachedinfo if _cached['ischrono'] is None: sortidx = _dates.__array__().ravel().argsort() sortflag = (sortidx == np.arange(_dates.size)).all() if sortflag: _cached['chronidx'] = None else: _cached['chronidx'] = sortidx _cached['ischrono'] = sortflag return _dates
def date_array(dlist=None, start_date=None, end_date=None, length=None, freq=None, autosort=False): """ Factory function for constructing a :class:`DateArray`. Parameters ---------- dlist : {sequence, DateArray}, optional If not None, :keyword:`dlist` must be any of these possibilities: * an existing :class:`DateArray` object; * a sequence of :class:`Date` objects with the same frequency; * a sequence of :class:`datetime.datetime` objects; * a sequence of dates in string format; * a sequence of integers corresponding to the representation of :class:`Date` objects. In any of the last four possibilities, the :keyword:`freq` parameter must also be given. start_date : {var}, optional First date of a continuous :class:`DateArray`. This parameter is used only if :keyword:`dlist` is None. In that case, one of the :keyword:`end_date` or the :keyword:`length` parameters must be given. end_date : {var}, optional Last date of the output. Use this parameter in combination with :keyword:`start_date` to create a continuous :class:`DateArray`. length : {int}, optional Length of the output. Use this parameter in combination with :keyword:`start_date` to create a continuous :class:`DateArray`. autosort : {True, False}, optional Whether the input dates must be sorted in chronological order. Notes ----- * When the input is a list of dates, the dates are **not** sorted. Use ``autosort = True`` to sort the dates by chronological order. * If `start_date` is a :class:`Date` object and `freq` is None, the frequency of the output is ``start_date.freq``. Returns ------- output : :class:`DateArray` object. """ freq = check_freq(freq) # Case #1: we have a list ................... if dlist is not None: # Already a DateArray.................... if isinstance(dlist, DateArray): if (freq != _c.FR_UND) and (dlist.freq != check_freq(freq)): # Convert to the new frequency dlist = dlist.asfreq() else: # Take a view so that we don't propagate modifications.... # ... in _cachedinfo. dlist = dlist.view() if autosort: dlist.sort_chronologically() return dlist # Make sure it's a sequence, else that's a start_date if hasattr(dlist, '__len__') and not isinstance(dlist, basestring): dlist = _listparser(dlist, freq=freq) if autosort: dlist.sort_chronologically() return dlist elif start_date is not None: if end_date is not None: dmsg = "What starting date should be used ? '%s' or '%s' ?" raise DateError, dmsg % (dlist, start_date) else: (start_date, end_date) = (dlist, start_date) else: start_date = dlist # Case #2: we have a starting date .......... if start_date is None: if length == 0: return DateArray([], freq=freq) raise InsufficientDateError if not isinstance(start_date, Date): try: start_date = Date(freq, start_date) except: dmsg = "Starting date should be a valid Date instance! " dmsg += "(got '%s' instead)" % type(start_date) raise DateError, dmsg # Check if we have an end_date if end_date is None: if length is None: length = 1 else: try: end_date = Date(start_date.freq, end_date) except: raise DateError, "Ending date should be a valid Date instance!" # Make sure end_date is after start_date if (end_date < start_date): (start_date, end_date) = (end_date, start_date) length = int(end_date - start_date) + 1 # dlist = np.arange(length, dtype=np.int) dlist += start_date.value if freq == _c.FR_UND: freq = start_date.freq # Transform the dates and set the cache dates = dlist.view(DateArray) dates.freq = freq dates._cachedinfo.update(ischrono=True, chronidx=np.array([], dtype=int)) return dates
def convert_to_float(datearray, ofreq): """ Convert a :class:`~scikits.timeseries.DateArray` object from a ndarray of integers to a ndarray of float at a lower frequency. Parameters ---------- datearray : DateArray Input :class:`~scikits.timeseries.DateArray` to convert. ofreq : var Valid frequency specifier. Notes ----- This function is currently restricted to conversion between annual (``'A'``), quarterly (``'Q'``), monthly (``'M'``) and daily (``'D'``) frequencies only. """ if not isinstance(datearray, DateArray): raise TypeError("The input should be a valid DateArray instance !"\ " (got '%s' instead)" % type(datearray)) errmsg = "Not implemented for the frequencies ('%s', '%s')" # freqdict = dict([(f, check_freq(f)) for f in ('A', 'Q', 'M', 'D')]) ifreq = datearray.freq ofreq = check_freq(ofreq) errmsg = "Not implemented for the frequencies ('%s', '%s')" % \ (check_freq_str(ifreq), check_freq_str(ofreq)) if ifreq < ofreq: output = datearray.asfreq(ofreq).tovalue().astype(float) elif ifreq == ofreq: output = datearray.tovalue().astype(float) # Quarterly......... elif (ifreq >= freqdict['Q']) and (ifreq < freqdict['M']): if (ofreq >= freqdict['A']) and (ofreq < freqdict['Q']): output = datearray.years.astype(float) + (datearray.quarters - 1.) / 4. # Monthly........... elif ifreq == freqdict['M']: #... to annual if (ofreq >= freqdict['A']) and (ofreq < freqdict['Q']): output = datearray.years.astype(float) + (datearray.months - 1) / 12. else: raise NotImplementedError(errmsg) # Daily ............ elif ifreq == freqdict['D']: # ... to annual if (ofreq >= freqdict['A']) and (ofreq < freqdict['Q']): output = datearray.asfreq('A') output = output.tovalue().astype(float) + \ (datearray.yeardays - 1.) / output.yeardays.astype(float) # ... to quarterly elif (ofreq >= freqdict['Q']) and (ofreq < freqdict['M']): raise NotImplementedError # ... to monthly elif ofreq == freqdict['M']: output = datearray.asfreq('M') output = output.tovalue().astype(float) + \ (datearray.days - 1.) / output.days.astype(float) # ... to other else: raise NotImplementedError(errmsg) # Less than daily elif ifreq > freqdict['D']: raise NotImplementedError(errmsg) else: raise NotImplementedError(errmsg) return output