[Scipy-svn] r2819 - in trunk/Lib/sandbox/timeseries: . addons addons/tests tests
scipy-svn at scipy.org
scipy-svn at scipy.org
Sat Mar 3 18:00:26 EST 2007
Author: pierregm
Date: 2007-03-03 17:00:20 -0600 (Sat, 03 Mar 2007)
New Revision: 2819
Modified:
trunk/Lib/sandbox/timeseries/__init__.py
trunk/Lib/sandbox/timeseries/addons/filters.py
trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py
trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py
trunk/Lib/sandbox/timeseries/tdates.py
trunk/Lib/sandbox/timeseries/tests/test_dates.py
trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
trunk/Lib/sandbox/timeseries/tseries.py
Log:
tdates : separated the case 'D'/'U' in Date
: improved the handling of 'U' freq
tseries : mask_period : fixed mask_period for multivariables
got rid of extra condition on end_date, start_date
set the default to inplace=False
: TimeSeries : fixed a bug when length was not None
: fixed end/start_date for multivariables.
filters : revert to initial implementation
Modified: trunk/Lib/sandbox/timeseries/__init__.py
===================================================================
--- trunk/Lib/sandbox/timeseries/__init__.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/__init__.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -23,6 +23,8 @@
from tmulti import *
import reportlib
from reportlib import *
+import plotlib
+import addons
__all__ = ['tdates', 'tseries','tmulti','reportlib']
Modified: trunk/Lib/sandbox/timeseries/addons/filters.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/filters.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/addons/filters.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -29,8 +29,21 @@
#####---------------------------------------------------------------------------
#---- --- Moving average functions ---
#####---------------------------------------------------------------------------
-def __expmave(data, n, tol):
- """helper function for expmave"""
+def expmave(data, n, tol=1e-6):
+ """Calculates the exponential moving average of a series.
+
+:Parameters:
+ data : ndarray
+ Data as a valid (subclass of) ndarray or MaskedArray. In particular,
+ TimeSeries objects are valid here.
+ n : int
+ Time periods. The smoothing factor is 2/(n + 1)
+ tol : float, *[1e-6]*
+ Tolerance for the definition of the mask. When data contains masked
+ values, this parameter determinea what points in the result should be masked.
+ Values in the result that would not be "significantly" impacted (as
+ determined by this parameter) by the masked values are left unmasked.
+"""
data = marray(data, copy=True, subok=True)
ismasked = (data._mask is not nomask)
data._mask = N.zeros(data.shape, bool_)
@@ -48,44 +61,7 @@
data._mask[0] = True
#
return data
-
-def expmave(data, n, tol=1e-6,
- centered=False, trailing=False):
- """Calculates the exponential moving average of a series.
-:Parameters:
- data : ndarray
- Data as a valid (subclass of) ndarray or MaskedArray. In particular,
- TimeSeries objects are valid here.
- n : int
- Time periods. The smoothing factor is 2/(n + 1).
- tol : float, *[1e-6]*
- Tolerance for the definition of the mask. When data contains masked
- values, this parameter determinea what points in the result should be masked.
- Values in the result that would not be "significantly" impacted (as
- determined by this parameter) by the masked values are left unmasked.
- centered : boolean, *[False]*
- If both centered and trailing are False, then centered is forced to
- True. If centered, the result at position i is the average of the
- trailing result with n=n//2, and an equivalent calculation operating in
- the reverse direction on the series.
- trailing : boolean, *[False]*
- If trailing is True, the result at position i uses only data points at,
- or before, position i.
-"""
- if not centered and not trailing:
- centered = True
- elif centered and trailing:
- raise ValueError("Cannot specify both centered and trailing")
-
- if trailing:
- return __expmave(data, n, tol=tol)
- else:
- rev_result = __expmave(data[::-1], n//2, tol=tol)[::-1]
- fwd_result = __expmave(data, n//2, tol=tol)
- return (rev_result + fwd_result)/N.array(2, dtype=data.dtype)
-
-
def weightmave(data, n):
data = marray(data, subok=True, copy=True)
data._mask = N.zeros(data.shape, bool_)
@@ -109,31 +85,23 @@
#...............................................................................
-def running_window(data, window_type, window_size,
- centered=False, trailing=False):
- """Applies a running window of type window_type and size window_size on the
-data. Returns a (subclass of) MaskedArray.
-
+def running_window(data, window_type, window_size):
+ """Applies a running window of type window_type and size window_size on the
+ data.
+
+ Returns a (subclass of) MaskedArray. The k first and k last data are always
+ masked (with k=window_size//2). When data has a missing value at position i,
+ the result has missing values in the interval [i-k:i+k+1].
+
+
:Parameters:
data : ndarray
- Data to process. The array should be at most 2D. On 2D arrays, the
- window
+ Data to process. The array should be at most 2D. On 2D arrays, the window
is applied recursively on each column.
window_type : string/tuple/float
Window type (see Notes)
window_size : integer
The width of the window.
- centered : boolean, *[False]*
- If both centered and trailing are False, then centered is forced to
- True. If centered, the result at position i uses data points from
- [i-k:i+k+1] in the calculation. The k first and k last data are always
- masked (with k=window_size//2). When data has a missing value at
- position i, the result has missing values in the interval [i-k:i+k+1].
- trailing : boolean, *[False]*
- If trailing is True, the result at position i uses data points from
- [i-window_size:i+1] in the calculation.the first "window_size" data
- points are always masked. When data has a missing value at position i,
- the result has missing values in the interval [i-window_size:i+1].
Notes
-----
@@ -148,24 +116,14 @@
Note also that only boxcar has been thoroughly tested.
"""
-
- if not centered and not trailing:
- centered = True
- elif centered and trailing:
- raise ValueError("Cannot specify both centered and trailing")
-
-
+ #
data = marray(data, copy=True, subok=True)
if data._mask is nomask:
data._mask = N.zeros(data.shape, bool_)
window = get_window(window_type, window_size, fftbins=False)
- n = len(data)
-
- if centered: k = window_size//2
- else: k = 0
-
+ (n, k) = (len(data), window_size//2)
+ #
if data.ndim == 1:
-
data._data.flat = convolve(data._data, window)[k:n+k] / float(window_size)
data._mask[:] = ((convolve(getmaskarray(data), window) > 0)[k:n+k])
elif data.ndim == 2:
@@ -175,39 +133,25 @@
data._mask[:,i] = (convolve(data._mask[:,i], window) > 0)[k:n+k]
else:
raise ValueError, "Data should be at most 2D"
-
- if centered:
- data._mask[:k] = data._mask[-k:] = True
- else:
- data._mask[:window_size] = True
+ data._mask[:k] = data._mask[-k:] = True
return data
-def running_mean(data, width,
- centered=False, trailing=False):
- """Computes the running mean of size width on the data. Returns a
-(subclass of) MaskedArray.
-
+def running_mean(data, width):
+ """Computes the running mean of size width on the data.
+
+ Returns a (subclass of) MaskedArray. The k first and k last data are always
+ masked (with k=window_size//2). When data has a missing value at position i,
+ the result has missing values in the interval [i-k:i+k+1].
+
:Parameters:
data : ndarray
Data to process. The array should be at most 2D. On 2D arrays, the window
is applied recursively on each column.
window_size : integer
- The width of the window.
- centered : boolean, *[False]*
- If both centered and trailing are False, then centered is forced to
- True. If centered, the result at position i uses data points from
- [i-k:i+k+1] in the calculation. The k first and k last data are always
- masked (with k=window_size//2). When data has a missing value at
- position i, the result has missing values in the interval [i-k:i+k+1].
- trailing : boolean, *[False]*
- If trailing is True, the result at position i uses data points from
- [i-window_size:i+1] in the calculation.the first "window_size" data
- points are always masked. When data has a missing value at position i,
- the result has missing values in the interval [i-window_size:i+1]."""
+ The width of the window.
+ """
+ return running_window(data, 'boxcar', width)
- return running_window(data, 'boxcar', width,
- centered=centered, trailing=trailing)
-
################################################################################
if __name__ == '__main__':
from maskedarray.testutils import assert_equal, assert_almost_equal
Modified: trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/addons/tests/test_filters.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -16,18 +16,15 @@
from numpy.testing import NumpyTest, NumpyTestCase
import maskedarray.testutils
-#reload(maskedarray.testutils)
from maskedarray.testutils import *
import maskedarray.core as coremodule
-#reload(coremodule)
from maskedarray.core import MaskedArray, masked
import tseries
from tseries import time_series, thisday
import addons.filters
-reload(addons.filters)
from addons.filters import running_mean
Modified: trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py
===================================================================
--- trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/addons/tests/test_interpolate.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -14,11 +14,9 @@
from numpy.testing import NumpyTest, NumpyTestCase
import maskedarray.testutils
-#reload(maskedarray.testutils)
from maskedarray.testutils import *
import maskedarray.core as coremodule
-#reload(coremodule)
from maskedarray.core import MaskedArray, masked
from addons.interpolate import backward_fill, forward_fill, interp_masked1d
Modified: trunk/Lib/sandbox/timeseries/tdates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tdates.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tdates.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -3,12 +3,12 @@
:author: Pierre GF Gerard-Marchant & Matt Knox
:contact: pierregm_at_uga_dot_edu - mattknox_ca_at_hotmail_dot_com
-:version: $Id: tdates.py 2805 2007-03-01 21:40:02Z mattknox_ca $
+:version: $Id$
"""
-__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author: mattknox_ca $)"
+__author__ = "Pierre GF Gerard-Marchant & Matt Knox ($Author$)"
__version__ = '1.0'
-__revision__ = "$Revision: 2805 $"
-__date__ = '$Date: 2007-03-01 16:40:02 -0500 (Thu, 01 Mar 2007) $'
+__revision__ = "$Revision$"
+__date__ = '$Date$'
import datetime as dt
@@ -35,7 +35,6 @@
from parser import DateFromString, DateTimeFromString
import tcore as corelib
-import tcore as _c
import cseries
@@ -49,6 +48,7 @@
'period_break'
]
+
#####---------------------------------------------------------------------------
#---- --- Date Info ---
#####---------------------------------------------------------------------------
@@ -147,40 +147,40 @@
value = int(value)
if isinstance(value, str):
- if self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
+ if self.freqstr in ('H', 'T', 'S'):
self.datetime = DateTimeFromString(value)
else:
self.datetime = DateFromString(value)
-
- elif self.freq == _c.FR_SEC:
- self.datetime = secondlyOriginDate + dt.timedelta(seconds=value)
- elif self.freq == _c.FR_MIN:
- self.datetime = minutelyOriginDate + dt.timedelta(minutes=value)
- elif self.freq == _c.FR_HR:
- self.datetime = hourlyOriginDate + dt.timedelta(hours=value)
- elif self.freq in (_c.FR_DAY, _c.FR_UND):
- self.datetime = dt.datetime.fromordinal(value)
- elif self.freq == _c.FR_BUS:
+ elif self.freqstr == 'A':
+ self.datetime = dt.datetime(value, 1, 1)
+ elif self.freqstr == 'B':
valtmp = (value - 1)//5
self.datetime = dt.datetime.fromordinal(value + valtmp*2)
- elif self.freq == _c.FR_WK:
- self.datetime = dt.datetime(1,1,7) + \
- dt.timedelta(days=(value-1)*7)
- elif self.freq == _c.FR_MTH:
+# elif self.freqstr in 'DU':
+ elif self.freqstr == 'D':
+ self.datetime = dt.datetime.fromordinal(value)
+ elif self.freqstr == 'U':
+ self.datetime = int(value)
+ elif self.freqstr == 'H':
+ self.datetime = hourlyOriginDate + dt.timedelta(hours=value)
+ elif self.freqstr == 'M':
year = (value - 1)//12 + 1
month = value - (year - 1)*12
self.datetime = dt.datetime(year, month, 1)
- elif self.freq == _c.FR_QTR:
+ elif self.freqstr == 'Q':
year = (value - 1)//4 + 1
month = (value - (year - 1)*4)*3
self.datetime = dt.datetime(year, month, 1)
- elif self.freq == _c.FR_ANN:
- self.datetime = dt.datetime(value, 1, 1)
- else:
- raise ValueError("unrecognized frequency: "+str(self.freq))
+ elif self.freqstr == 'S':
+ self.datetime = secondlyOriginDate + dt.timedelta(seconds=value)
+ elif self.freqstr == 'T':
+ self.datetime = minutelyOriginDate + dt.timedelta(minutes=value)
+ elif self.freqstr == 'W':
+ self.datetime = dt.datetime(1,1,7) + \
+ dt.timedelta(days=(value-1)*7)
elif string is not None:
- if self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
+ if self.freqstr in ('H', 'T', 'S'):
self.datetime = DateTimeFromString(string)
else:
self.datetime = DateFromString(string)
@@ -194,32 +194,31 @@
# First, some basic checks.....
if year is None:
raise InsufficientDateError
- if self.freq in (_c.FR_BUS, _c.FR_DAY, _c.FR_WK, _c.FR_UND):
+ if self.freqstr in 'BDWU':
if month is None or day is None:
raise InsufficientDateError
- elif self.freq == _c.FR_MTH:
+ elif self.freqstr == 'M':
if month is None:
raise InsufficientDateError
day = 1
- elif self.freq == _c.FR_QTR:
+ elif self.freqstr == 'Q':
if quarter is None:
raise InsufficientDateError
month = quarter * 3
day = 1
- elif self.freq == _c.FR_ANN:
+ elif self.freqstr == 'A':
month = 1
day = 1
- elif self.freq == _c.FR_SEC:
+ elif self.freqstr == 'S':
if month is None or day is None or second is None:
raise InsufficientDateError
- if self.freq in (_c.FR_BUS, _c.FR_DAY, _c.FR_WK,
- _c.FR_MTH, _c.FR_QTR, _c.FR_ANN):
+ if self.freqstr in ['A','B','D','M','Q','W']:
self.datetime = truncateDate(self.freq, dt.datetime(year, month, day))
- if self.freq == _c.FR_BUS:
+ if self.freqstr == 'B':
if self.datetime.isoweekday() in [6,7]:
raise ValueError("Weekend passed as business day")
- elif self.freq in (_c.FR_HR, _c.FR_MIN, _c.FR_SEC):
+ elif self.freqstr in 'HTS':
if hour is None:
if minute is None:
if second is None:
@@ -240,9 +239,6 @@
self.datetime = truncateDate(self.freqstr,
dt.datetime(year, month, day,
hour, minute, second))
- else:
- raise ValueError("unrecognized frequency: "+str(self.freq))
-
self.value = self.__value()
def __getitem__(self, indx):
@@ -340,45 +336,53 @@
def __value(self):
"Converts the date to an integer, depending on the current frequency."
- # Secondly......
- if self.freq == _c.FR_SEC:
- delta = (self.datetime - secondlyOriginDate)
- val = delta.days*86400 + delta.seconds
- # Minutely......
- elif self.freq == _c.FR_MIN:
- delta = (self.datetime - minutelyOriginDate)
- val = delta.days*1440 + delta.seconds/(60)
- # Hourly........
- elif self.freq == _c.FR_HR:
- delta = (self.datetime - hourlyOriginDate)
- val = delta.days*24 + delta.seconds/(3600)
- # Daily/undefined
- elif self.freq in (_c.FR_DAY, _c.FR_UND):
- val = self.datetime.toordinal()
+ # Annual .......
+ if self.freqstr == 'A':
+ val = self.datetime.year
+ # Quarterly.....
+ elif self.freqstr == 'Q':
+ val = (self.datetime.year-1)*4 + self.datetime.month//3
+ # Monthly.......
+ elif self.freqstr == 'M':
+ val = (self.datetime.year-1)*12 + self.datetime.month
+ # Weekly........
+ elif self.freqstr == 'W':
+ val = self.datetime.toordinal()//7
# Business days.
- elif self.freq == _c.FR_BUS:
+ elif self.freqstr == 'B':
days = self.datetime.toordinal()
weeks = days // 7
val = days - weeks*2
- # Weekly........
- elif self.freq == _c.FR_WK:
- val = self.datetime.toordinal()//7
- # Monthly.......
- elif self.freq == _c.FR_MTH:
- val = (self.datetime.year-1)*12 + self.datetime.month
- # Quarterly.....
- elif self.freq == _c.FR_QTR:
- val = (self.datetime.year-1)*4 + self.datetime.month//3
- # Annual .......
- elif self.freq == _c.FR_ANN:
- val = self.datetime.year
-
+ # Daily.........
+# elif self.freqstr in 'DU':
+ elif self.freqstr == 'D':
+ val = self.datetime.toordinal()
+ # Undefined.....
+ elif self.freqstr == 'U':
+ if not hasattr(self.datetime, 'toordinal'):
+ val = self.datetime
+ else:
+ val = self.datetime.toordinal()
+ # Hourly........
+ elif self.freqstr == 'H':
+ delta = (self.datetime - hourlyOriginDate)
+ val = delta.days*24 + delta.seconds/(3600)
+ # Minutely......
+ elif self.freqstr == 'T':
+ delta = (self.datetime - minutelyOriginDate)
+ val = delta.days*1440 + delta.seconds/(60)
+ # Secondly......
+ elif self.freqstr == 'S':
+ delta = (self.datetime - secondlyOriginDate)
+ val = delta.days*86400 + delta.seconds
return int(val)
#......................................................
def strfmt(self, fmt):
"Formats the date"
if fmt is None:
fmt = self.default_fmtstr[self.freqstr]
+ if self.freqstr == 'U':
+ return str(self.value)
return cseries.strfmt(self.datetime, fmt)
def __str__(self):
@@ -389,6 +393,9 @@
#......................................................
def toordinal(self):
"Returns the date as an ordinal."
+ # FIXME: We shouldn't need the test if we were in C
+ if self.freqstr == 'U':
+ return self.value
return self.datetime.toordinal()
def fromordinal(self, ordinal):
@@ -425,26 +432,26 @@
def truncateDate(freq, datetime):
"Chops off the irrelevant information from the datetime object passed in."
- freq = corelib.check_freq(freq)
- if freq == _c.FR_MIN:
+ freqstr = corelib.check_freqstr(freq)
+ if freqstr == 'A':
+ return dt.datetime(datetime.year, 1, 1)
+ elif freqstr == 'Q':
+ return dt.datetime(datetime.year, monthToQuarter(datetime.month)*3, 1)
+ elif freqstr == 'M':
+ return dt.datetime(datetime.year, datetime.month, 1)
+ elif freqstr == 'W':
+ d = datetime.toordinal()
+ return dt.datetime.fromordinal(d + (7 - d % 7) % 7)
+ elif freqstr in 'BD':
+ if freq == 'B' and datetime.isoweekday() in (6,7):
+ raise ValueError("Weekend passed as business day")
+ return dt.datetime(datetime.year, datetime.month, datetime.day)
+ elif freqstr == 'H':
return dt.datetime(datetime.year, datetime.month, datetime.day, \
+ datetime.hour)
+ elif freqstr == 'T':
+ return dt.datetime(datetime.year, datetime.month, datetime.day, \
datetime.hour, datetime.minute)
- elif freq == _c.FR_HR:
- return dt.datetime(datetime.year, datetime.month, datetime.day, \
- datetime.hour)
- elif freq in (_c.FR_BUS, _c.FR_DAY):
- if freq == _c.FR_BUS and datetime.isoweekday() in (6,7):
- raise ValueError("Weekend passed as business day")
- return dt.datetime(datetime.year, datetime.month, datetime.day)
- elif freq == _c.FR_WK:
- d = datetime.toordinal()
- return dt.datetime.fromordinal(d + (7 - d % 7) % 7)
- elif freq == _c.FR_MTH:
- return dt.datetime(datetime.year, datetime.month, 1)
- elif freq == _c.FR_QTR:
- return dt.datetime(datetime.year, monthToQuarter(datetime.month)*3, 1)
- elif freq == _c.FR_ANN:
- return dt.datetime(datetime.year, 1, 1)
else:
return datetime
@@ -455,20 +462,18 @@
def thisday(freq):
"Returns today's date, at the given frequency `freq`."
- freq = corelib.check_freq(freq)
+ freqstr = corelib.check_freqstr(freq)
tempDate = dt.datetime.now()
# if it is Saturday or Sunday currently, freq==B, then we want to use Friday
- if freq == _c.FR_BUS and tempDate.isoweekday() >= 6:
+ if freqstr == 'B' and tempDate.isoweekday() >= 6:
tempDate = tempDate - dt.timedelta(days=(tempDate.isoweekday() - 5))
- if freq in (_c.FR_BUS,_c.FR_DAY,
- _c.FR_HR,_c.FR_SEC,_c.FR_MIN,
- _c.FR_WK,_c.FR_UND):
+ if freqstr in ('B','D','H','S','T','W','U'):
return Date(freq, datetime=tempDate)
- elif freq == _c.FR_MTH:
+ elif freqstr == 'M':
return Date(freq, year=tempDate.year, month=tempDate.month)
- elif freq == _c.FR_QTR:
+ elif freqstr == 'Q':
return Date(freq, year=tempDate.year, quarter=monthToQuarter(tempDate.month))
- elif freq == _c.FR_ANN:
+ elif freqstr == 'A':
return Date(freq, year=tempDate.year)
today = thisday
@@ -478,9 +483,9 @@
dateNum = tempDate.hour + float(tempDate.minute)/60
checkNum = day_end_hour + float(day_end_min)/60
if dateNum < checkNum:
- return thisday(_c.FR_BUS) - 1
+ return thisday('B') - 1
else:
- return thisday(_c.FR_BUS)
+ return thisday('B')
def asfreq(date, toFreq, relation="BEFORE"):
"""Returns a date converted to another frequency `toFreq`, according to the
@@ -494,9 +499,9 @@
if not isinstance(date, Date):
raise DateError, "Date should be a valid Date instance!"
- if date.freq == _c.FR_UND:
+ if date.freqstr == 'U':
warnings.warn("Undefined frequency: assuming daily!")
- fromfreq = _c.FR_DAY
+ fromfreq = corelib.freq_revdict['D']
else:
fromfreq = date.freq
@@ -638,7 +643,8 @@
return r
def __repr__(self):
- return ndarray.__repr__(self)
+ return ndarray.__repr__(self)[:-1] + \
+ ",\n freq='%s')" % self.freqstr
#......................................................
__add__ = _datearithmetics('__add__', asdates=True)
__radd__ = _datearithmetics('__add__', asdates=True)
@@ -723,7 +729,10 @@
# Note: we better try to cache the result
if self._cachedinfo['toord'] is None:
# diter = (Date(self.freq, value=d).toordinal() for d in self)
- diter = (d.toordinal() for d in self)
+ if self.freq == -9999:
+ diter = (d.value for d in self)
+ else:
+ diter = (d.toordinal() for d in self)
toord = numeric.fromiter(diter, dtype=float_)
self._cachedinfo['toord'] = toord
return self._cachedinfo['toord']
@@ -749,9 +758,11 @@
return self
tofreq = corelib.check_freq(freq)
if tofreq == self.freq:
- return self
+ return self
+ _rel = relation.upper()[0]
fromfreq = self.freq
- _rel = relation.upper()[0]
+ if fromfreq == -9999:
+ fromfreq = 6000
new = cseries.asfreq(numeric.asarray(self), fromfreq, tofreq, _rel)
return DateArray(new, freq=freq)
#......................................................
@@ -842,30 +853,30 @@
ddif = numeric.asarray(numpy.diff(dates))
ddif.sort()
if ddif[0] == ddif[-1] == 1.:
- fcode = _c.FR_DAY
+ fcode = 'D'
elif (ddif[0] == 1.) and (ddif[-1] == 3.):
- fcode = _c.FR_BUS
+ fcode = 'B'
elif (ddif[0] > 3.) and (ddif[-1] == 7.):
- fcode = _c.FR_WK
+ fcode = 'W'
elif (ddif[0] >= 28.) and (ddif[-1] <= 31.):
- fcode = _c.FR_MTH
+ fcode = 'M'
elif (ddif[0] >= 90.) and (ddif[-1] <= 92.):
- fcode = _c.FR_QTR
+ fcode = 'Q'
elif (ddif[0] >= 365.) and (ddif[-1] <= 366.):
- fcode = _c.FR_ANN
+ fcode = 'A'
elif numpy.abs(24.*ddif[0] - 1) <= 1e-5 and \
numpy.abs(24.*ddif[-1] - 1) <= 1e-5:
- fcode = _c.FR_HR
+ fcode = 'H'
elif numpy.abs(1440.*ddif[0] - 1) <= 1e-5 and \
numpy.abs(1440.*ddif[-1] - 1) <= 1e-5:
- fcode = _c.FR_MIN
+ fcode = 'T'
elif numpy.abs(86400.*ddif[0] - 1) <= 1e-5 and \
numpy.abs(86400.*ddif[-1] - 1) <= 1e-5:
- fcode = _c.FR_SEC
+ fcode = 'S'
else:
warnings.warn("Unable to estimate the frequency! %.3f<>%.3f" %\
(ddif[0], ddif[-1]))
- fcode = _c.FR_UND
+ fcode = 'U'
return fcode
@@ -1042,7 +1053,7 @@
if __name__ == '__main__':
import maskedarray.testutils
from maskedarray.testutils import assert_equal
- if 1:
+ if 0:
dlist = ['2007-%02i' % i for i in range(1,5)+range(7,13)]
mdates = date_array_fromlist(dlist, 'M')
# Using an integer
@@ -1052,12 +1063,12 @@
lag = mdates.find_dates(mdates[0])
print mdates[lag]
assert_equal(mdates[lag], mdates[0])
- if 1:
+ if 0:
hodie = today('D')
D = DateArray(today('D'))
assert_equal(D.freq, 6000)
- if 1:
+ if 0:
freqs = [x[0] for x in corelib.freq_dict.values() if x[0] != 'U']
print freqs
for f in freqs:
@@ -1066,9 +1077,16 @@
assert(Date(freq=f, value=today.value) == today)
if 1:
- D = date_array(start_date=thisday('D'), length=5)
- Dstr = D.tostring()
- assert_equal(D.tostring(), Dstr)
- DL = D[[0,-1]]
- assert_equal(DL.tostring(), Dstr[[0,-1]])
-
\ No newline at end of file
+ D = date_array(freq='U', start_date=Date('U',1), length=10)
+
+ if 1:
+ dlist = ['2007-01-%02i' % i for i in (1,2,4,5,7,8,10,11,13)]
+
+
+ ords = numpy.fromiter((DateTimeFromString(s).toordinal() for s in dlist),
+ float_)
+
+ if 1:
+ "Tests the automatic sorting of dates."
+ D = date_array_fromlist(dlist=['2006-01','2005-01','2004-01'],freq='M')
+ assert_equal(D.view(N.ndarray), [24037, 24049, 24061])
\ No newline at end of file
Modified: trunk/Lib/sandbox/timeseries/tests/test_dates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_dates.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tests/test_dates.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -715,9 +715,11 @@
assert_equal(mdates>=mdates[-4], [0,0,0,0,0,0,1,1,1,1])
dlist = ['2006-%02i' % i for i in range(1,5)+range(7,13)]
mdates = date_array_fromlist(dlist).asfreq('M')
+ #CHECK : Oops, what were we supposed to do here ?
def test_getsteps(self):
+ "Tests the getsteps method"
dlist = ['2007-01-%02i' %i for i in (1,2,3,4,8,9,10,11,12,15)]
ddates = date_array_fromlist(dlist)
assert_equal(ddates.get_steps(), [1,1,1,4,1,1,1,1,3])
@@ -729,8 +731,13 @@
assert_equal(empty_darray.isvalid(), True)
assert_equal(empty_darray.get_steps(), None)
+ def test_cachedinfo(self):
+ D = date_array(start_date=thisday('D'), length=5)
+ Dstr = D.tostring()
+ assert_equal(D.tostring(), Dstr)
+ DL = D[[0,-1]]
+ assert_equal(DL.tostring(), Dstr[[0,-1]])
-
###############################################################################
#------------------------------------------------------------------------------
if __name__ == "__main__":
Modified: trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_timeseries.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tests/test_timeseries.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -25,8 +25,9 @@
import maskedarray.testutils
from maskedarray.testutils import assert_equal, assert_array_equal
-from timeseries import Date, date_array_fromlist, date_array, thisday
-from timeseries import time_series, TimeSeries, adjust_endpoints, \
+from timeseries import tseries
+from timeseries.tseries import Date, date_array_fromlist, date_array, thisday
+from timeseries.tseries import time_series, TimeSeries, adjust_endpoints, \
mask_period, align_series, fill_missing_dates, tsmasked, concatenate_series
class test_creation(NumpyTestCase):
@@ -422,6 +423,15 @@
mask = mask_period(series, start, end, inside=False, include_edges=False,
inplace=False)
assert_equal(mask._mask, [1,1,1,1,1,0,0,0,0,0,0,0,1,1,1])
+ # Now w/ multivariables
+ data = masked_array(numeric.arange(30).reshape(-1,2), dtype=float_)
+ series = time_series(data, dates=dates)
+ mask = mask_period(series, start, end, inside=True, include_edges=True,
+ inplace=False)
+ result = N.array([0,0,0,0,0,1,1,1,1,1,1,1,0,0,0])
+ assert_equal(mask._mask, result.repeat(2).reshape(-1,2))
+
+
#
def test_pickling(self):
"Tests pickling/unpickling"
Modified: trunk/Lib/sandbox/timeseries/tseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tseries.py 2007-03-02 18:54:55 UTC (rev 2818)
+++ trunk/Lib/sandbox/timeseries/tseries.py 2007-03-03 23:00:20 UTC (rev 2819)
@@ -308,7 +308,7 @@
if len(dshape) > 0:
if length is None:
length = dshape[0]
- newdates = date_array(start_date=start_date, length=dshape[0],
+ newdates = date_array(start_date=start_date, length=length,
freq=freq)
else:
newdates = date_array([], freq=freq)
@@ -610,17 +610,25 @@
@property
def start_date(self):
"""Returns the first date of the series."""
- if self._dates.size != 0:
- return self._dates[0]
+ _dates = self._dates
+ dsize = _dates.size
+ if dsize == 0:
+ return None
+ elif dsize == 1:
+ return _dates[0]
else:
- return None
+ return Date(self.freq, _dates.flat[0])
@property
def end_date(self):
"""Returns the last date of the series."""
- if self._dates.size != 0:
- return self._dates[-1]
+ _dates = self._dates
+ dsize = _dates.size
+ if dsize == 0:
+ return None
+ elif dsize == 1:
+ return _dates[-1]
else:
- return None
+ return Date(self.freq, _dates.flat[-1])
def isvalid(self):
"""Returns whether the series has no duplicate/missing dates."""
@@ -920,14 +928,16 @@
##### --------------------------------------------------------------------------
#---- ... Additional functions ...
##### --------------------------------------------------------------------------
-def mask_period(data, start_date=None, end_date=None,
- inside=True, include_edges=True, inplace=True):
+def mask_period(data, period=None, start_date=None, end_date=None,
+ inside=True, include_edges=True, inplace=False):
"""Returns x as an array masked where dates fall outside the selection period,
as well as where data are initially missing (masked).
:Parameters:
data : Timeseries
Data to process
+ period : Sequence
+ A sequence of (starting date, ending date).
start_date : string/Date *[None]*
Starting date. If None, uses the first date of the series.
end_date : string/Date *[None]*
@@ -943,47 +953,50 @@
data = masked_array(data, subok=True, copy=not inplace)
if not isTimeSeries(data):
raise ValueError,"Data should be a valid TimeSeries!"
+ dates = data._dates
+ if dates.ndim == 1:
+ dates_lims = dates[[0,-1]]
+ else:
+ dates_lim = dates.ravel()[[0,-1]]
+ # Check the period .....................
+ if period is not None and isinstance(period, (tuple, list, ndarray)):
+ (start_date, end_date) = (period[0], period[-1])
# Check the starting date ..............
if start_date is None:
- start_date = data._dates[0]
+ start_date = dates_lim[0]
elif isinstance(start_date, str):
start_date = Date(data.freq, string=start_date)
elif not isinstance(start_date, Date):
raise DateError,"Starting date should be a valid Date object!"
- start_date = max(start_date, data.dates[0])
# Check the ending date ................
if end_date is None:
- end_date = data._dates[-1]
+ end_date = dates_lim[-1]
elif isinstance(end_date, str):
end_date = Date(data.freq, string=end_date)
elif not isinstance(end_date, Date):
raise DateError,"Starting date should be a valid Date object!"
- end_date = min(end_date, data.dates[-1])
# Constructs the selection mask .........
+ dates = data.dates
if inside:
if include_edges:
- selection = (data.dates >= start_date) & (data.dates <= end_date)
+ selection = (dates >= start_date) & (dates <= end_date)
else:
- selection = (data.dates > start_date) & (data.dates < end_date)
+ selection = (dates > start_date) & (dates < end_date)
else:
if include_edges:
- selection = (data.dates <= start_date) | (data.dates >= end_date)
+ selection = (dates <= start_date) | (dates >= end_date)
else:
- selection = (data.dates < start_date) | (data.dates > end_date)
- # Process the data:
- if data._mask is nomask:
- data._mask = selection
- else:
- data._mask += selection
+ selection = (dates < start_date) | (dates > end_date)
+ data[selection] = masked
return data
def mask_inside_period(data, start_date=None, end_date=None,
- include_edges=True, inplace=True):
+ include_edges=True, inplace=False):
"""Masks values falling inside a given range of dates."""
return mask_period(data, start_date=start_date, end_date=end_date,
inside=True, include_edges=include_edges, inplace=inplace)
def mask_outside_period(data, start_date=None, end_date=None,
- include_edges=True, inplace=True):
+ include_edges=True, inplace=False):
"""Masks values falling outside a given range of dates."""
return mask_period(data, start_date=start_date, end_date=end_date,
inside=False, include_edges=include_edges, inplace=inplace)
@@ -1374,6 +1387,8 @@
dlist = ['2007-01-%02i' % i for i in range(1,11)]
dates = date_array_fromlist(dlist)
data = masked_array(numeric.arange(10), mask=[1,0,0,0,0]*2, dtype=float_)
+
+ if 0:
ser1d = time_series(data, dlist)
serfolded = ser1d.reshape((5,2))
@@ -1385,21 +1400,17 @@
sertrans = serfolded.transpose()
assert_equal(sertrans.shape, (2,5))
- if 1:
- dlist = ['2007-01-%02i' % i for i in range(1,16)]
- data = masked_array(numeric.arange(15), mask=[1,0,0,0,0]*3, dtype=float_)
- series = time_series(data, dlist)
- series.mask = nomask
- (start, end) = ('2007-01-06', '2007-01-12')
- mask = mask_period(series, start, end, inside=True, include_edges=True,
- inplace=False)
- assert_equal(mask._mask, N.array([0,0,0,0,0,1,1,1,1,1,1,1,0,0,0]))
- mask = mask_period(series, start, end, inside=True, include_edges=False,
- inplace=False)
- assert_equal(mask._mask, [0,0,0,0,0,0,1,1,1,1,1,0,0,0,0])
- mask = mask_period(series, start, end, inside=False, include_edges=True,
- inplace=False)
- assert_equal(mask._mask, [1,1,1,1,1,1,0,0,0,0,0,1,1,1,1])
- mask = mask_period(series, start, end, inside=False, include_edges=False,
- inplace=False)
- assert_equal(mask._mask, [1,1,1,1,1,0,0,0,0,0,0,0,1,1,1])
\ No newline at end of file
+ if 1:
+ data = dates
+ series = time_series(data, dates)
+ assert(isinstance(series, TimeSeries))
+ assert_equal(series._dates, dates)
+ assert_equal(series._data, data)
+ assert_equal(series.freqstr, 'D')
+
+ series[5] = MA.masked
+
+ # ensure that series can be represented by a string after masking a value
+ # (there was a bug before that prevented this from working when using a
+ # DateArray for the data)
+ strrep = str(series)
\ No newline at end of file
More information about the Scipy-svn
mailing list