Permalink
Browse files

ENH: added quarter-based slicing to datetimeindex

  • Loading branch information...
1 parent b3b5473 commit 65a1342dc9e27b62f1469af68a46c44d5a8c2835 @adamklein committed Mar 28, 2012
Showing with 22 additions and 8 deletions.
  1. +6 −6 pandas/core/datetools.py
  2. +6 −1 pandas/core/index.py
  3. +9 −0 pandas/tests/test_datetime64.py
  4. +1 −1 pandas/tests/test_interval.py
View
@@ -731,7 +731,7 @@ class DateParseError(Exception):
_dtparser = parser.parser()
-# patterns for quarters like 4Q2005, 05Q1
+# patterns for quarters like '4Q2005', '05Q1'
qpat1full = re.compile(r'(\d)Q(\d\d\d\d)')
qpat2full = re.compile(r'(\d\d\d\d)Q(\d)')
qpat1 = re.compile(r'(\d)Q(\d\d)')
@@ -749,15 +749,15 @@ def parse_time_string(arg):
try:
default = datetime(1,1,1).replace(hour=0, minute=0,
- second=0, microsecond=0)
+ second=0, microsecond=0)
# special handling for possibilities eg, 2Q2005, 2Q05, 2005Q1, 05Q1
if len(arg) in [4, 6]:
if len(arg) == 4:
qpats = [(qpat1, 1), (qpat2, 0)]
else:
qpats = [(qpat1full, 1), (qpat2full, 0)]
-
+
for pat, yfirst in qpats:
qparse = pat.match(arg)
if qparse is not None:
@@ -767,10 +767,10 @@ def parse_time_string(arg):
yi, qi = 2, 1
q = int(qparse.group(yi))
y = int(qparse.group(qi))
- if y < 2000:
+ if y < 2000:
y += 2000
ret = default.replace(year=y, month=(q-1)*3+1)
- return ret, ret.strftime('%Y/%m'), 'quarter'
+ return ret, ret, 'quarter'
dayfirst = print_config.date_dayfirst
yearfirst = print_config.date_yearfirst
@@ -783,7 +783,7 @@ def parse_time_string(arg):
reso = 'year'
stopped = False
for attr in ["year", "month", "day", "hour",
- "minute", "second", "microsecond"]:
+ "minute", "second", "microsecond"]:
can_be_zero = ['hour', 'minute', 'second', 'microsecond']
value = getattr(parsed, attr)
if value is not None and (value != 0 or attr in can_be_zero):
View
@@ -1591,7 +1591,12 @@ def _partial_date_slice(self, reso, parsed):
i1, i2 = np.searchsorted(self.asi8, [t1.value, t2.value])
return slice(i1, i2+1)
elif reso == 'quarter':
- raise NotImplementedError('Quarter slicing not implemented yet')
+ qe = (((parsed.month - 1) + 2) % 12) + 1 # two months ahead
+ d = lib.monthrange(parsed.year, qe)[1] # at end of month
+ t1 = to_timestamp(datetime(parsed.year, parsed.month, 1))
+ t2 = to_timestamp(datetime(parsed.year, qe, d))
+ i1, i2 = np.searchsorted(self.asi8, [t1.value, t2.value])
+ return slice(i1, i2+1)
raise KeyError
@@ -468,6 +468,15 @@ def test_slice_year(self):
df = DataFrame(np.random.rand(len(dti), 5), index=dti)
self.assertEquals(len(df.ix['2005']), 261)
+ def test_slice_quarter(self):
+ dti = DatetimeIndex(freq='D', start=datetime(2000,6,1), periods=500)
+
+ s = Series(np.arange(len(dti)), index=dti)
+ self.assertEquals(len(s['2001Q1']), 90)
+
+ df = DataFrame(np.random.rand(len(dti), 5), index=dti)
+ self.assertEquals(len(df.ix['1Q01']), 90)
+
def test_slice_month(self):
dti = DatetimeIndex(freq='D', start=datetime(2005,1,1), periods=500)
@@ -950,7 +950,7 @@ def test_iindex_multiples(self):
self.assertEquals(i, Interval('1/1/2010 12:05:15', '5S'))
i = Interval('1/1/2010 12:05:18', '5S')
- self.assertEquals(i.resample('1S', how='E'),
+ self.assertEquals(i.resample('1S', how='E'),
Interval('1/1/2010 12:05:19', '1S'))
class TestMethods(TestCase):

0 comments on commit 65a1342

Please sign in to comment.