예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
 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
예제 #5
0
 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)
예제 #6
0
 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
예제 #7
0
    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)
예제 #8
0
 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
예제 #9
0
 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
예제 #10
0
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
예제 #11
0
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
예제 #12
0
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
예제 #13
0
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