[Scipy-svn] r2754 - in trunk/Lib/sandbox/timeseries: . tests
scipy-svn at scipy.org
scipy-svn at scipy.org
Thu Feb 22 22:17:04 EST 2007
Author: pierregm
Date: 2007-02-22 21:16:56 -0600 (Thu, 22 Feb 2007)
New Revision: 2754
Added:
trunk/Lib/sandbox/timeseries/.project
Modified:
trunk/Lib/sandbox/timeseries/tdates.py
trunk/Lib/sandbox/timeseries/tests/test_dates.py
trunk/Lib/sandbox/timeseries/tests/test_multitimeseries.py
trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
trunk/Lib/sandbox/timeseries/tmulti.py
trunk/Lib/sandbox/timeseries/tseries.py
Log:
tdates : fixed a pb in DateArray where the frequence was not properly updated
: optimization of DateArray.__new__
tseries: optimization of TimeSeries.__getitem__
: fixed a pb w/ _tsarraymethod when ondates=True
: modified __check_index to allow access to rows/columns of a reshaped 1d series.
: add transpose
tmulti : update to take into account the modidications of mrecords
Added: trunk/Lib/sandbox/timeseries/.project
===================================================================
--- trunk/Lib/sandbox/timeseries/.project 2007-02-22 21:00:31 UTC (rev 2753)
+++ trunk/Lib/sandbox/timeseries/.project 2007-02-23 03:16:56 UTC (rev 2754)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>scipy_svn_timeseries</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.python.pydev.PyDevBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.python.pydev.pythonNature</nature>
+ </natures>
+</projectDescription>
Modified: trunk/Lib/sandbox/timeseries/tdates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tdates.py 2007-02-22 21:00:31 UTC (rev 2753)
+++ trunk/Lib/sandbox/timeseries/tdates.py 2007-02-23 03:16:56 UTC (rev 2754)
@@ -25,7 +25,6 @@
from numpy.core.numerictypes import generic
import maskedarray as MA
-#reload(MA)
import mx.DateTime as mxD
from mx.DateTime.Parser import DateFromString as mxDFromString
@@ -40,7 +39,8 @@
'DateError', 'ArithmeticDateError', 'FrequencyDateError','InsufficientDateError',
'datearray','date_array', 'date_array_fromlist', 'date_array_fromrange',
'day_of_week','day_of_year','day','month','quarter','year','hour','minute','second',
-'truncateDate','monthToQuarter','thisday','today','prevbusday','asfreq'
+'truncateDate','monthToQuarter','thisday','today','prevbusday','asfreq',
+'period_break'
]
@@ -224,6 +224,9 @@
hour, minute, second))
self.value = self.__value()
+ def __getitem__(self, indx):
+ return self
+
@property
def day(self):
"Returns the day of month."
@@ -385,6 +388,7 @@
# A date is always valid by itself, but we need the object to support the function
# when we're working with singletons.
return True
+ #......................................................
#####---------------------------------------------------------------------------
@@ -488,6 +492,52 @@
'equal','not_equal','less','less_equal', 'greater','greater_equal',
'isnan']
+class _datearithmetics(object):
+ """Defines a wrapper for arithmetic methods.
+Instead of directly calling a ufunc, the corresponding method of the `array._data`
+object is called instead.
+If `asdates` is True, a DateArray object is returned , else a regular ndarray
+is returned.
+ """
+ def __init__ (self, methodname, asdates=True):
+ """
+:Parameters:
+ - `methodname` (String) : Method name.
+ """
+ self.methodname = methodname
+ self._asdates = asdates
+ self.__doc__ = getattr(methodname, '__doc__')
+ self.obj = None
+ #
+ def __get__(self, obj, objtype=None):
+ self.obj = obj
+ return self
+ #
+ def __call__ (self, other, *args, **kwargs):
+ "Execute the call behavior."
+ instance = self.obj
+ freq = instance.freq
+ if 'context' not in kwargs:
+ kwargs['context'] = 'DateOK'
+ method = getattr(super(DateArray,instance), self.methodname)
+ if isinstance(other, DateArray):
+ if other.freq != freq:
+ raise FrequencyDateError("Cannot operate on dates", \
+ freq, other.freq)
+ elif isinstance(other, Date):
+ if other.freq != freq:
+ raise FrequencyDateError("Cannot operate on dates", \
+ freq, other.freq)
+ other = other.value
+ elif isinstance(other, ndarray):
+ if other.dtype.kind not in ['i','f']:
+ raise ArithmeticDateError
+ if self._asdates:
+ return instance.__class__(method(other, *args),
+ freq=freq)
+ else:
+ return method(other, *args)
+
class DateArray(ndarray):
"""Defines a ndarray of dates, as ordinals.
@@ -506,12 +556,14 @@
if freq is None:
_freq = getattr(dates, 'freq', -9999)
else:
- _freq = freq
- cls._defaultfreq = corelib.check_freq(freq)
+ _freq = corelib.check_freq(freq)
+ cls._defaultfreq = corelib.check_freq(_freq)
# Get the dates ..........
- _dates = numeric.array(dates, copy=copy, dtype=int_, subok=1).view(cls)
+ _dates = numeric.array(dates, copy=copy, dtype=int_, subok=1)
if _dates.ndim == 0:
_dates.shape = (1,)
+ _dates = _dates.view(cls)
+ _dates.freq = _freq
return _dates
def __array_wrap__(self, obj, context=None):
@@ -551,6 +603,17 @@
def __repr__(self):
return ndarray.__repr__(self)
#......................................................
+ __add__ = _datearithmetics('__add__', asdates=True)
+ __radd__ = _datearithmetics('__add__', asdates=True)
+ __sub__ = _datearithmetics('__sub__', asdates=True)
+ __rsub__ = _datearithmetics('__rsub__', asdates=True)
+ __le__ = _datearithmetics('__le__', asdates=False)
+ __lt__ = _datearithmetics('__lt__', asdates=False)
+ __ge__ = _datearithmetics('__ge__', asdates=False)
+ __gt__ = _datearithmetics('__gt__', asdates=False)
+ __eq__ = _datearithmetics('__eq__', asdates=False)
+ __ne__ = _datearithmetics('__ne__', asdates=False)
+ #......................................................
@property
def day(self):
"Returns the day of month."
@@ -717,64 +780,10 @@
"Returns whether the DateArray is valid: no missing/duplicated dates."
return (self.isfull() and not self.has_duplicated_dates())
#......................................................
-class _datearithmetics(object):
- """Defines a wrapper for arithmetic methods.
-Instead of directly calling a ufunc, the corresponding method of the `array._data`
-object is called instead.
-If `asdates` is True, a DateArray object is returned , else a regular ndarray
-is returned.
- """
- def __init__ (self, methodname, asdates=True):
- """
-:Parameters:
- - `methodname` (String) : Method name.
- """
- self.methodname = methodname
- self._asdates = asdates
- self.__doc__ = getattr(methodname, '__doc__')
- self.obj = None
- #
- def __get__(self, obj, objtype=None):
- self.obj = obj
- return self
- #
- def __call__ (self, other, *args, **kwargs):
- "Execute the call behavior."
- instance = self.obj
- freq = instance.freq
- if 'context' not in kwargs:
- kwargs['context'] = 'DateOK'
- method = getattr(super(DateArray,instance), self.methodname)
- if isinstance(other, DateArray):
- if other.freq != freq:
- raise FrequencyDateError("Cannot operate on dates", \
- freq, other.freq)
-# other =
- elif isinstance(other, Date):
- if other.freq != freq:
- raise FrequencyDateError("Cannot operate on dates", \
- freq, other.freq)
- other = other.value
- elif isinstance(other, ndarray):
- if other.dtype.kind not in ['i','f']:
- raise ArithmeticDateError
- if self._asdates:
- return instance.__class__(method(other, *args),
- freq=freq)
- else:
- return method(other, *args)
+
#............................
-DateArray.__add__ = _datearithmetics('__add__', asdates=True)
-DateArray.__radd__ = _datearithmetics('__add__', asdates=True)
-DateArray.__sub__ = _datearithmetics('__sub__', asdates=True)
-DateArray.__rsub__ = _datearithmetics('__rsub__', asdates=True)
-DateArray.__le__ = _datearithmetics('__le__', asdates=False)
-DateArray.__lt__ = _datearithmetics('__lt__', asdates=False)
-DateArray.__ge__ = _datearithmetics('__ge__', asdates=False)
-DateArray.__gt__ = _datearithmetics('__gt__', asdates=False)
-DateArray.__eq__ = _datearithmetics('__eq__', asdates=False)
-DateArray.__ne__ = _datearithmetics('__ne__', asdates=False)
+
#####---------------------------------------------------------------------------
#---- --- DateArray functions ---
#####---------------------------------------------------------------------------
@@ -892,6 +901,8 @@
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! "
@@ -905,7 +916,7 @@
else:
if not isDate(end_date):
raise DateError, "Ending date should be a valid Date instance!"
- length = end_date - start_date
+ length = int(end_date - start_date)
if include_last:
length += 1
# dlist = [(start_date+i).value for i in range(length)]
@@ -968,6 +979,20 @@
second = _frommethod('second')
+def period_break(dates, period):
+ """Returns the indices where the given period changes.
+
+:Parameters:
+ dates : DateArray
+ Array of dates to monitor.
+ period : string
+ Name of the period to monitor.
+ """
+ current = getattr(dates, period)
+ previous = getattr(dates-1, period)
+ return (current - previous).nonzero()[0]
+
+
################################################################################
if __name__ == '__main__':
@@ -981,4 +1006,17 @@
# Using a date
lag = mdates.find_dates(mdates[0])
print mdates[lag]
- assert_equal(mdates[lag], mdates[0])
\ No newline at end of file
+ assert_equal(mdates[lag], mdates[0])
+ if 1:
+ hodie = today('D')
+ D = DateArray(today('D'))
+ assert_equal(D.freq, 6000)
+
+ if 1:
+ freqs = [x[0] for x in corelib.freq_dict.values() if x[0] != 'U']
+ print freqs
+ for f in freqs:
+ print f
+ today = thisday(f)
+ assert(Date(freq=f, value=today.value) == today)
+
\ No newline at end of file
Modified: trunk/Lib/sandbox/timeseries/tests/test_dates.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_dates.py 2007-02-22 21:00:31 UTC (rev 2753)
+++ trunk/Lib/sandbox/timeseries/tests/test_dates.py 2007-02-23 03:16:56 UTC (rev 2754)
@@ -26,15 +26,12 @@
from maskedarray.testutils import assert_equal, assert_array_equal
import timeseries.tdates as tdates
-reload(tdates)
#from timeseries import tdates
-##reload(tdates)
#from timeseries.tdates import date_array_fromlist, Date, DateArray, date_array,\
# mxDFromString, today
from timeseries.tdates import *
from timeseries.tdates import mxDFromString
from timeseries import tcore
-#reload(tcore)
class test_creation(NumpyTestCase):
Modified: trunk/Lib/sandbox/timeseries/tests/test_multitimeseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_multitimeseries.py 2007-02-22 21:00:31 UTC (rev 2753)
+++ trunk/Lib/sandbox/timeseries/tests/test_multitimeseries.py 2007-02-23 03:16:56 UTC (rev 2754)
@@ -18,16 +18,15 @@
from numpy.testing.utils import build_err_msg
import maskedarray.testutils
-#reload(maskedarray.testutils)
from maskedarray.testutils import assert_equal, assert_array_equal
import maskedarray.core as MA
import maskedarray.mrecords as MR
+from maskedarray.mrecords import addfield
from maskedarray.core import getmaskarray, nomask, masked_array
from timeseries import tmulti
-reload(tmulti)
from timeseries.tmulti import MultiTimeSeries, TimeSeries,\
fromarrays, fromtextfile, fromrecords, \
date_array, time_series
@@ -63,11 +62,14 @@
assert_equal(mts['f0']._mask, m)
#
assert(isinstance(mts[0], MultiTimeSeries))
- assert_equal(mts[0]._data, mrec[0])
- assert_equal(mts[0]._dates, dates[0])
+ assert_equal(mts._data[0], mrec[0])
+ # We can't use assert_equal here, as it tries to convert the tuple into a singleton
+ assert(mts[0]._data.view(N.ndarray) == mrec[0])
+ assert_equal(mts._dates[0], dates[0])
+ assert_equal(mts[0]._dates, dates[0])
#
assert(isinstance(mts['2007-01'], MultiTimeSeries))
- assert_equal(mts['2007-01']._data, mrec[0])
+ assert(mts['2007-01']._data == mrec[0])
assert_equal(mts['2007-01']._dates, dates[0])
#
assert_equal(mts.f0, time_series(d, dates=dates, mask=m))
@@ -131,7 +133,7 @@
def test_addfield(self):
"Tests addfield"
[d, m, mrec, dlist, dates, ts, mts] = self.data
- mts.addfield(masked_array(d+10, mask=m[::-1]))
+ mts = addfield(mts, masked_array(d+10, mask=m[::-1]))
assert_equal(mts.f2, d+10)
assert_equal(mts.f2._mask, m[::-1])
Modified: trunk/Lib/sandbox/timeseries/tests/test_timeseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tests/test_timeseries.py 2007-02-22 21:00:31 UTC (rev 2753)
+++ trunk/Lib/sandbox/timeseries/tests/test_timeseries.py 2007-02-23 03:16:56 UTC (rev 2754)
@@ -26,7 +26,6 @@
from maskedarray.testutils import assert_equal, assert_array_equal
from timeseries import tseries
-#reload(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
@@ -263,6 +262,44 @@
assert_equal(ser_x[:,0], time_series(a, d))
assert_equal(ser_x[:,:], ser_x)
+ def test_onnd(self):
+ "Tests getitem on a nD series"
+ hodie = thisday('D')
+ # Case 1D
+ series = time_series(N.arange(5), mask=[1,0,0,0,0], start_date=hodie)
+ assert_equal(series[0], 0)
+ # Case 1D + mask
+ series = time_series(N.arange(5), mask=[1,0,0,0,0], start_date=hodie)
+ assert series[0] is tsmasked
+ # Case 2D
+ series = time_series(N.arange(10).reshape(5,2), start_date=hodie)
+ assert_equal(len(series), 5)
+ assert_equal(series[0], [[0,1]])
+ assert_equal(series[0]._dates, (hodie))
+ assert_equal(series[:,0], [0,2,4,6,8])
+ assert_equal(series[:,0]._dates, series._dates)
+ # Case 2D + mask
+ series = time_series(N.arange(10).reshape(5,2), start_date=hodie,
+ mask=[[1,1],[0,0],[0,0],[0,0],[0,0]])
+ assert_equal(len(series), 5)
+ assert_equal(series[0], [[0,1]])
+ assert_equal(series[0]._mask, [[1,1]])
+ assert_equal(series[0]._dates, (hodie))
+ assert_equal(series[:,0]._data, [0,2,4,6,8])
+ assert_equal(series[:,0]._mask, [1,0,0,0,0])
+ assert_equal(series[:,0]._dates, series._dates)
+ # Case 3D
+ series = time_series(N.arange(30).reshape(5,3,2), start_date=hodie)
+ x = series[0]
+ assert_equal(len(series), 5)
+ assert_equal(series[0], [[[0,1],[2,3],[4,5]]])
+ assert_equal(series[0]._dates, (hodie))
+ assert_equal(series[:,0], series._data[:,0])
+ assert_equal(series[:,0]._dates, series._dates)
+ x = series[:,:,0]
+ assert_equal(series[:,:,0], series._data[:,:,0])
+ assert_equal(series[:,:,0]._dates, series._dates)
+
class test_functions(NumpyTestCase):
"Some getitem tests"
def __init__(self, *args, **kwds):
Modified: trunk/Lib/sandbox/timeseries/tmulti.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tmulti.py 2007-02-22 21:00:31 UTC (rev 2753)
+++ trunk/Lib/sandbox/timeseries/tmulti.py 2007-02-23 03:16:56 UTC (rev 2754)
@@ -27,8 +27,6 @@
from numpy.core.records import fromarrays as recfromarrays
import maskedarray as MA
-#import numpy.core.ma as MA
-#reload(MA)
#MaskedArray = MA.MaskedArray
from maskedarray.core import MaskedArray, MAError, default_fill_value, \
masked_print_option
@@ -36,7 +34,6 @@
make_mask_none, mask_or, masked_array, filled
import maskedarray.mrecords as MR
-#reload(MR)
from maskedarray.mrecords import _checknames, _guessvartypes, openfile,\
MaskedRecords
from maskedarray.mrecords import fromrecords as mrecfromrecords
@@ -74,7 +71,6 @@
formats += ','
return formats[:-1]
-
@@ -102,12 +98,12 @@
byteorder=byteorder, aligned=aligned)
#
if isinstance(data, MultiTimeSeries):
- cls._defaultfieldmask = data._series._fieldmask
- cls._defaulthardmask = data._series._hardmask | hard_mask
- cls._fill_value = data._series._fill_value
- return data._data.view(cls)
+# if copy:
+# data = data.copy()
+ data._hardmask = data._hardmask | hard_mask
+ return data
# .......................................
- _data = MaskedRecords(data, mask=mask, dtype=dtype, **mroptions)
+ _data = MaskedRecords(data, mask=mask, dtype=dtype, **mroptions).view(cls)
if dates is None:
length = _getdatalength(data)
newdates = date_array(start_date=start_date, length=length,
@@ -116,72 +112,67 @@
newdates = date_array(dlist=dates, freq=freq)
else:
newdates = dates
- cls._defaultdates = newdates
- cls._defaultobserved = observed
+ _data._dates = newdates
+ _data._observed = observed
cls._defaultfieldmask = _data._fieldmask
#
- return _data.view(cls)
-#
-# #..................................
-# def __array_wrap__(self, obj, context=None):
-# """Special hook for ufuncs.
-#Wraps the numpy array and sets the mask according to context.
-# """
-## mclass = self.__class__
-# #..........
-# if context is None:
-## return mclass(obj, mask=self._mask, copy=False)
-# return MaskedArray(obj, mask=self._mask, copy=False,
-# dtype=obj.dtype,
-# fill_value=self.fill_value, )
-# #..........
-# (func, args) = context[:2]
-#
-## return mclass(obj, copy=False, mask=m)
-# return MultiTimeSeries(obj, copy=False, mask=m,)
-## dtype=obj.dtype, fill_value=self._fill_value)
- def __array_finalize__(self,obj):
- if isinstance(obj, MultiTimeSeries):
- self.__dict__.update(_dates=obj._dates,
- _series=obj._series,
- _data=obj._series._data,
- _fieldmask=obj._series._fieldmask,
- _hardmask=obj._series._hardmask,
- _fill_value=obj._fill_value
+ return _data
+
+ def __array_finalize__(self,obj):
+ if isinstance(obj, (MaskedRecords)):
+ self.__dict__.update(_fieldmask=obj._fieldmask,
+ _hardmask=obj._hardmask,
+ _fill_value=obj._fill_value,
)
+ if isinstance(obj, MultiTimeSeries):
+ self.__dict__.update(observed=obj.observed,
+ _dates=obj._dates)
+ else:
+ self.__dict__.update(observed=None,
+ _dates=[])
else:
- self.__dict__.update(_data = obj.view(recarray),
- _dates = self._defaultdates,
- _series = MaskedRecords(obj, dtype=obj.dtype),
- _fieldmask = self._defaultfieldmask,
- _hardmask = self._defaulthardmask,
- fill_value = self._fill_value
+ self.__dict__.update(_dates = [],
+ observed=None,
+ _fieldmask = nomask,
+ _hardmask = False,
+ fill_value = None
)
- MultiTimeSeries._defaultfieldmask = nomask
- MultiTimeSeries._defaulthardmask = False
return
+
+
+ def _getdata(self):
+ "Returns the data as a recarray."
+ return self.view(recarray)
+ _data = property(fget=_getdata)
+
+ def _getseries(self):
+ "Returns the data as a MaskedRecord array."
+ return self.view(MaskedRecords)
+ _series = property(fget=_getseries)
+
#......................................................
def __getattribute__(self, attr):
- try:
- # Returns a generic attribute
- return object.__getattribute__(self,attr)
- except AttributeError:
- # OK, so attr must be a field name
- pass
- # Get the list of fields ......
- _names = self.dtype.names
- _local = self.__dict__
- _mask = _local['_fieldmask']
- if attr in _names:
- _data = _local['_data']
- obj = numeric.asarray(_data.__getattribute__(attr)).view(MaskedArray)
- obj._mask = make_mask(_mask.__getattribute__(attr))
- return obj
- elif attr == '_mask':
- if self.size > 1:
- return _mask.view((bool_, len(self.dtype))).all(1)
- return _mask.view((bool_, len(self.dtype)))
- raise AttributeError,"No attribute '%s' !" % attr
+ return MaskedRecords.__getattribute__(self,attr)
+# try:
+# # Returns a generic attribute
+# return object.__getattribute__(self,attr)
+# except AttributeError:
+# # OK, so attr must be a field name
+# pass
+# # Get the list of fields ......
+# _names = self.dtype.names
+# _local = self.__dict__
+# _mask = _local['_fieldmask']
+# if attr in _names:
+# _data = self._data
+# obj = numeric.asarray(_data.__getattribute__(attr)).view(MaskedArray)
+# obj._mask = make_mask(_mask.__getattribute__(attr))
+# return obj
+# elif attr == '_mask':
+# if self.size > 1:
+# return _mask.view((bool_, len(self.dtype))).all(1)
+# return _mask.view((bool_, len(self.dtype)))
+# raise AttributeError,"No attribute '%s' !" % attr
def __setattr__(self, attr, val):
newattr = attr not in self.__dict__
@@ -195,7 +186,7 @@
exctype, value = sys.exc_info()[:2]
raise exctype, value
else:
- if attr not in list(self.dtype.names) + ['_mask']:
+ if attr not in list(self.dtype.names) + ['_dates','_mask']:
return ret
if newattr: # We just added this one
try: # or this setattr worked on an internal
@@ -234,59 +225,36 @@
_localdict = self.__dict__
# We want a field ........
if indx in self.dtype.names:
- obj = _localdict['_series'][indx].view(TimeSeries)
+ obj = self._data[indx].view(TimeSeries)
+ obj._dates = _localdict['_dates']
obj._mask = make_mask(_localdict['_fieldmask'][indx])
return obj
# We want some elements ..
- (sindx, dindx) = super(MultiTimeSeries, self)._TimeSeries__checkindex(indx)
- return MultiTimeSeries(_localdict['_series'][sindx],
- dates=_localdict['_dates'][dindx],
-# mask=_localdict['_fieldmask'][indx],
- dtype=self.dtype)
+ (sindx, dindx) = self._TimeSeries__checkindex(indx)
+# obj = numeric.array(self._data[sindx],
+# copy=False, subok=True).view(type(self))
+ obj = numeric.array(self._data[sindx], copy=False, subok=True)
+ obj = obj.view(type(self))
+ obj.__dict__.update(_dates=_localdict['_dates'][dindx],
+ _fieldmask=_localdict['_fieldmask'][sindx],
+ _fill_value=_localdict['_fill_value'])
+ return obj
def __getslice__(self, i, j):
"""Returns the slice described by [i,j]."""
_localdict = self.__dict__
(si, di) = super(MultiTimeSeries, self)._TimeSeries__checkindex(i)
(sj, dj) = super(MultiTimeSeries, self)._TimeSeries__checkindex(j)
- return MultiTimeSeries(_localdict['_data'][si:sj],
- mask=_localdict['_fieldmask'][si:sj],
- dates=_localdict['_dates'][di:dj],
- dtype=self.dtype)
+ newdata = self._data[si:sj].view(type(self))
+ newdata.__dict__.update(_dates=_localdict['_dates'][di:dj],
+ _mask=_localdict['_fieldmask'][si:sj])
+ return newdata
def __setslice__(self, i, j, value):
"""Sets the slice described by [i,j] to `value`."""
- _localdict = self.__dict__
- d = _localdict['_data']
- t = _localdict['_dates']
- m = _localdict['_fieldmask']
- names = self.dtype.names
- if value is masked:
- for n in names:
- m[i:j][n] = masked
- elif not self._hardmask:
- fval = filled(value)
- mval = getmaskarray(value)
- for n in names:
- d[n][i:j] = fval
- m[n][i:j] = mval
- else:
- mindx = getmaskarray(self)[i:j]
- val = masked_array(value, mask=mindx, keep_mask=True)
- valmask = getmask(value)
- if valmask is nomask:
- for n in names:
- mval = mask_or(m[n][i:j], valmask)
- d[n][i:j][~mval] = filled(value)
- elif valmask.size > 1:
- for n in names:
- mval = mask_or(m[n][i:j], valmask)
- d[n][i:j][~mval] = fval[~mval]
- m[n][i:j] = mask_or(m[n][i:j], mval)
+ self.view(MaskedRecords).__setslice__(i,j,value)
+ return
- return MultiTimeSeries(d, mask=m, dates=t[i:j], dtype=self.dtype)
-
-
#......................................................
def __str__(self):
"""x.__str__() <==> str(x)
@@ -320,25 +288,6 @@
fmt % (' fill_value', self._fill_value),
' )'])
return str("\n".join(reprstr))
- #......................................................
- def view(self, obj):
- """Returns a view of the mrecarray."""
- try:
- if issubclass(obj, ndarray):
- return ndarray.view(self, obj)
- except TypeError:
- pass
- dtype = numeric.dtype(obj)
- if dtype.fields is None:
- return self.__array__().view(dtype)
- return ndarray.view(self, obj)
- #............................................
-# def harden_mask(self):
-# "Forces the mask to hard"
-# self._hardmask = True
-# def soften_mask(self):
-# "Forces the mask to soft"
-# self._hardmask = False
#.............................................
def copy(self):
"Returns a copy of the argument."
@@ -347,10 +296,8 @@
dates=_localdict['_dates'].copy(),
mask=_localdict['_fieldmask'].copy(),
dtype=self.dtype)
- #.............................................
- def addfield(self, newfield, newfieldname=None):
- MaskedRecords.addfield(self, newfield, newfieldname)
+
#####---------------------------------------------------------------------------
#---- --- Constructors ---
#####---------------------------------------------------------------------------
@@ -561,13 +508,11 @@
return MultiTimeSeries(_datalist, dates=newdates, dtype=mdescr)
-
-################################################################################
-
################################################################################
if __name__ == '__main__':
import numpy as N
+ from maskedarray.testutils import assert_equal
if 1:
d = N.arange(5)
m = MA.make_mask([1,0,0,1,1])
@@ -579,4 +524,17 @@
dates = date_array(dlist)
ts = time_series(mrec,dates)
mts = MultiTimeSeries(mrec,dates)
- self_data = [d, m, mrec, dlist, dates, ts, mts]
\ No newline at end of file
+ self_data = [d, m, mrec, dlist, dates, ts, mts]
+
+ if 1:
+ mts[:2] = 5
+ assert_equal(mts.f0._data, [5,5,2,3,4])
+ assert_equal(mts.f1._data, [5,5,2,1,0])
+ assert_equal(mts.f0._mask, [0,0,0,1,1])
+ assert_equal(mts.f1._mask, [0,0,0,0,1])
+ mts.harden_mask()
+ mts[-2:] = 5
+ assert_equal(mts.f0._data, [5,5,2,3,4])
+ assert_equal(mts.f1._data, [5,5,2,5,0])
+ assert_equal(mts.f0._mask, [0,0,0,1,1])
+ assert_equal(mts.f1._mask, [0,0,0,0,1])
\ No newline at end of file
Modified: trunk/Lib/sandbox/timeseries/tseries.py
===================================================================
--- trunk/Lib/sandbox/timeseries/tseries.py 2007-02-22 21:00:31 UTC (rev 2753)
+++ trunk/Lib/sandbox/timeseries/tseries.py 2007-02-23 03:16:56 UTC (rev 2754)
@@ -32,27 +32,23 @@
import numpy.core.fromnumeric as fromnumeric
import numpy.core.numeric as numeric
import numpy.core.umath as umath
-#from numpy.core.records import recarray
+from numpy.core.records import recarray
from numpy.core.records import fromarrays as recfromarrays
import maskedarray.core as MA
-#reload(MA)
from maskedarray.core import MaskedArray, MAError, masked, nomask, \
filled, getmask, getmaskarray, make_mask_none, mask_or, make_mask, \
masked_array
import tcore as corelib
-#reload(corelib)
from tcore import *
import tdates
-#reload(tdates)
from tdates import DateError, InsufficientDateError
from tdates import Date, isDate, DateArray, isDateArray, \
- date_array, date_array_fromlist, date_array_fromrange, thisday
+ date_array, date_array_fromlist, date_array_fromrange, thisday, today
import cseries
-#reload(cseries)
@@ -162,7 +158,8 @@
if dsize == tsize:
return True
elif data.ndim > 1:
- dsize = numeric.asarray(data.shape)[:-1].prod()
+ #dsize = numeric.asarray(data.shape)[:-1].prod()
+ dsize = data.shape[0]
if dsize == tsize:
return True
elif data.ndim == 0 and tsize <= 1:
@@ -241,11 +238,40 @@
func_series = getattr(super(TimeSeries, instance), _name)
result = func_series(*args)
if self._ondates:
- result._dates = getattr(instance._dates, _name)
+ result._dates = getattr(instance._dates, _name)(*args)
else:
result._dates = instance._dates
return result
+class _tsaxismethod(object):
+ """Defines a wrapper for array methods working on an axis (mean...).
+When called, returns a ndarray, as the result of the method applied on the series.
+ """
+ def __init__ (self, methodname):
+ """abfunc(fillx, filly) must be defined.
+ abinop(x, filly) = x for all x to enable reduce.
+ """
+ self._name = methodname
+ #
+ def __get__(self, obj, objtype=None):
+ self.obj = obj
+ return self
+ #
+ def __call__ (self, *args, **params):
+ "Execute the call behavior."
+ (_dates, _series) = (self.obj._dates, self.obj._series)
+ func = getattr(_series, self._name)
+ result = func(*args, **params)
+ if _dates.size == _series.size:
+ return result
+ else:
+ try:
+ axis = params.get('axis', args[0])
+ if axis in [-1, _series.ndim-1]:
+ result = TimeSeries(result, dates=_dates)
+ except IndexError:
+ pass
+ return result
class TimeSeries(MaskedArray, object):
"""Base class for the definition of time series.
@@ -284,9 +310,9 @@
if freq is not None and newdates.freq != freq:
newdates = newdates.tofreq(freq)
else:
- length = _getdatalength(data)
- if length > 0:
- newdates = date_array(start_date=start_date, length=length,
+ dshape = _data.shape
+ if len(dshape) > 0:
+ newdates = date_array(start_date=start_date, length=dshape[0],
freq=freq)
else:
newdates = date_array([], freq=freq)
@@ -304,8 +330,8 @@
#............................................
def __array_finalize__(self,obj):
MaskedArray.__array_finalize__(self, obj)
- self._dates = getattr(obj, '_dates', None)
- self.observed = getattr(obj, 'observed', self._defaultobserved)
+ self._dates = getattr(obj, '_dates', [])
+ self.observed = getattr(obj, 'observed', None)
return
#..................................
def __array_wrap__(self, obj, context=None):
@@ -323,7 +349,7 @@
"Checks the validity of an index."
if isinstance(indx, int):
return (indx, indx)
- if isinstance(indx, str):
+ elif isinstance(indx, str):
indx = self._dates.date_to_index(Date(self._dates.freq, string=indx))
return (indx, indx)
elif isDate(indx):
@@ -345,9 +371,12 @@
elif isinstance(indx, tuple):
if len(indx) > self.shape:
raise IndexError, "Too many indices"
- elif len(indx)==2:
- return (indx,indx[0])
- return (indx,indx[:-1])
+ if self._dates.size == self.size:
+ return (indx, indx)
+ return (indx,indx[0])
+# elif len(indx)==2:
+# return (indx,indx[0])
+# return (indx,indx[:-1])
elif isTimeSeries(indx):
indx = indx._series
if getmask(indx) is not nomask:
@@ -360,31 +389,47 @@
Returns the item described by i. Not a copy as in previous versions.
"""
(sindx, dindx) = self.__checkindex(indx)
- data = self._series[sindx]
- date = self._dates[dindx]
+ newdata = numeric.array(self._series[sindx], copy=False, subok=True)
+ newdate = self._dates[dindx]
m = self._mask
-
- singlepoint = (len(numeric.shape(date))==0)
-
+ singlepoint = (len(numeric.shape(newdate))==0)
if singlepoint:
- if data is not masked and self.ndim > 1:
- data = data.reshape((list((1,)) + list(data.shape)))
- date = date_array(start_date=date, length=1, freq=date.freq)
-
- if m is nomask:
- return TimeSeries(data, dates=date, mask=nomask, keep_mask=True,
- copy=False)
+ if newdata is masked:
+ newdata = tsmasked
+ newdata._dates = newdate
+ return newdata
+ elif self.ndim > 1:
+ # CHECK: use reshape, or set shape ?
+ newshape = (list((1,)) + list(newdata.shape))
+ newdata.shape = newshape
+ newdata = newdata.view(type(self))
+ newdata._dates = newdate
+ return newdata
+# CHECK : The implementation below should work, but does not. Why ?
+# newdata = numeric.array(self._data[sindx], copy=False)
+# newdates = self._dates[dindx]
+# if self._mask is not nomask:
+# newmask = self._mask.copy()[sindx]
+# else:
+# newmask = nomask
+# singlepoint = (len(numeric.shape(newdates))==0)
+# if singlepoint:
+# if newmask.ndim == 0 and newmask:
+# output = tsmasked
+# output._dates = newdates
+# return output
+# if self.ndim > 1:
+# # CHECK: use reshape, or set shape ?
+# newdata = newdata.reshape((list((1,)) + list(newdata.shape)))
+# if newmask is not nomask:
+# newmask.shape = newdata.shape
+# newdata = newdata.view(type(self))
+# newdata._dates = newdates
+# newdata._mask = newmask
+# return newdata
- mi = m[sindx]
- if mi.size == 1:
- if mi:
- output = tsmasked
- output._dates = date
- return output
- return TimeSeries(data, dates=date, mask=nomask)
- else:
- return TimeSeries(data, dates=date, mask=mi)
+
#........................
def __setitem__(self, indx, value):
"""x.__setitem__(i, y) <==> x[i]=y
@@ -465,7 +510,6 @@
__gt__ = _tsmathmethod('__gt__')
__ge__ = _tsmathmethod('__ge__')
- astype = _tsarraymethod('astype')
reshape = _tsarraymethod('reshape', ondates=True)
copy = _tsarraymethod('copy', ondates=True)
compress = _tsarraymethod('compress', ondates=True)
@@ -474,6 +518,17 @@
cumprod = _tsarraymethod('cumprod',ondates=False)
anom = _tsarraymethod('anom',ondates=False)
+ sum = _tsaxismethod('sum')
+ prod = _tsaxismethod('prod')
+ mean = _tsaxismethod('mean')
+ var = _tsaxismethod('var')
+ varu = _tsaxismethod('varu')
+ std = _tsaxismethod('std')
+ stdu = _tsaxismethod('stdu')
+ all = _tsaxismethod('all')
+ any = _tsaxismethod('any')
+
+
# def nonzero(self):
# """Returns a tuple of ndarrays, one for each dimension of the array,
# containing the indices of the non-zero elements in that dimension."""
@@ -599,6 +654,21 @@
"Converts the dates to another frequency, and adapt the data."
return convert(self, freq, func=func, position=position)
#.....................................................
+ def transpose(self, *axes):
+ if self._dates.size == self.size:
+ result = super(TimeSeries, self).transpose(*axes)
+ result._dates = self._dates.transpose(*axes)
+ else:
+ errmsg = "Operation not permitted on multi-variable series"
+ print "AXES:",axes
+ if (len(axes)==0) or axes[0] != 0:
+ raise ValueError, errmsg
+ else:
+ result = super(TimeSeries, self).transpose(*axes)
+ result._dates = self._dates
+ return result
+
+
def _attrib_dict(series, exclude=[]):
"""this function is used for passing through attributes of one
@@ -612,45 +682,7 @@
##--- ... Additional methods ...
##### --------------------------------------------------------------------------
-class _tsaxismethod(object):
- """Defines a wrapper for array methods working on an axis (mean...).
-When called, returns a ndarray, as the result of the method applied on the series.
- """
- def __init__ (self, methodname):
- """abfunc(fillx, filly) must be defined.
- abinop(x, filly) = x for all x to enable reduce.
- """
- self._name = methodname
- #
- def __get__(self, obj, objtype=None):
- self.obj = obj
- return self
- #
- def __call__ (self, *args, **params):
- "Execute the call behavior."
- (_dates, _series) = (self.obj._dates, self.obj._series)
- func = getattr(_series, self._name)
- result = func(*args, **params)
- if _series.ndim < 2 or _dates.size == _series.size:
- return result
- else:
- try:
- axis = params.get('axis', args[0])
- if axis in [-1, _series.ndim-1]:
- result = TimeSeries(result, dates=_dates)
- except IndexError:
- pass
- return result
#.......................................
-TimeSeries.sum = _tsaxismethod('sum')
-TimeSeries.prod = _tsaxismethod('prod')
-TimeSeries.mean = _tsaxismethod('mean')
-TimeSeries.var = _tsaxismethod('var')
-TimeSeries.varu = _tsaxismethod('varu')
-TimeSeries.std = _tsaxismethod('std')
-TimeSeries.stdu = _tsaxismethod('stdu')
-TimeSeries.all = _tsaxismethod('all')
-TimeSeries.any = _tsaxismethod('any')
class _tsblockedmethods(object):
@@ -668,7 +700,7 @@
#
def __call__ (self, *args, **params):
raise NotImplementedError
-TimeSeries.transpose = _tsarraymethod('transpose', ondates=True)
+#TimeSeries.transpose = _tsarraymethod('transpose', ondates=True)
TimeSeries.swapaxes = _tsarraymethod('swapaxes', ondates=True)
@@ -851,14 +883,15 @@
`data` :
Array of data.
"""
- data = numeric.asanyarray(data)
+ data = numeric.array(data, copy=False, subok=True)
if dates is None:
- length = _getdatalength(data)
- if length > 0:
+ dshape = data.shape
+ if len(dshape) > 0:
dates = date_array(start_date=start_date, end_date=end_date,
- length=length, include_last=include_last, freq=freq)
+ length=dshape[0], include_last=include_last,
+ freq=freq)
else:
- dates = date_array([], freq=freq)
+ dates = date_array([], freq=freq)
elif not isinstance(dates, DateArray):
dates = date_array(dlist=dates, freq=freq)
return TimeSeries(data=data, dates=dates, mask=mask, observed=observed,
@@ -1310,8 +1343,31 @@
################################################################################
if __name__ == '__main__':
- from maskedarray.testutils import assert_equal
+ from maskedarray.testutils import assert_equal, assert_array_equal
import numpy as N
-
-
+ if 1:
+ 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_)
+ ser1d = time_series(data, dlist)
+
+ serfolded = ser1d.reshape((5,2))
+ assert_equal(serfolded._dates.shape, (5,2))
+ assert_equal(serfolded[0], time_series([0,1],mask=[1,0],
+ start_date=dates[0]))
+ assert_equal(serfolded[:,0],
+ time_series(ser1d[::2], dates=dates[::2]))
+ sertrans = serfolded.transpose()
+ assert_equal(sertrans.shape, (2,5))
+
+ assert ser1d[0] is tsmasked
+ print "OK"
+ if 1:
+ hodie = today('D')
+ ser2d = time_series(N.arange(10).reshape(5,2), start_date=hodie,
+ mask=[[1,1],[0,0],[0,0],[0,0],[0,0]])
+ if 1:
+ hodie = today('D')
+ ser3d = time_series(N.arange(30).reshape(5,3,2), start_date=hodie,)
+
More information about the Scipy-svn
mailing list