Skip to content

Commit b7728c1

Browse files
committed
TST: resample test coverage etc. #1245
1 parent d8626fb commit b7728c1

File tree

7 files changed

+122
-89
lines changed

7 files changed

+122
-89
lines changed

pandas/tests/test_series.py

+4
Original file line numberDiff line numberDiff line change
@@ -2707,6 +2707,10 @@ def test_asfreq(self):
27072707
monthly_ts = daily_ts.asfreq(datetools.bmonthEnd)
27082708
self.assert_(np.array_equal(monthly_ts, ts))
27092709

2710+
result = ts[:0].asfreq('M')
2711+
self.assert_(len(result) == 0)
2712+
self.assert_(result is not ts)
2713+
27102714
def test_interpolate(self):
27112715
ts = Series(np.arange(len(self.ts), dtype=float), self.ts.index)
27122716

pandas/tseries/period.py

+27-52
Original file line numberDiff line numberDiff line change
@@ -21,44 +21,20 @@
2121
# Period logic
2222

2323

24-
def _period_field_accessor(name, alias=None):
25-
if alias is None:
26-
alias = name
24+
def _period_field_accessor(name, alias):
2725
def f(self):
2826
base, mult = _gfc(self.freq)
2927
return plib.get_period_field(alias, self.ordinal, base)
3028
f.__name__ = name
3129
return property(f)
3230

33-
def _field_accessor(name, alias=None):
34-
if alias is None:
35-
alias = name
31+
def _field_accessor(name, alias):
3632
def f(self):
3733
base, mult = _gfc(self.freq)
3834
return plib.get_period_field_arr(alias, self.values, base)
3935
f.__name__ = name
4036
return property(f)
4137

42-
def to_period(arg, freq=None):
43-
""" Attempts to convert arg to timestamp """
44-
if arg is None:
45-
return arg
46-
47-
if type(arg) == float:
48-
raise TypeError("Cannot convert a float to period")
49-
50-
return Period(arg, freq=freq)
51-
52-
def _to_quarterly(year, month, freq='Q-DEC'):
53-
fmonth = _freq_mod._month_numbers[_freq_mod._get_rule_month(freq)] + 1
54-
print fmonth
55-
mdiff = (month - fmonth) % 12
56-
if month >= fmonth:
57-
mdiff += 12
58-
59-
ordin = 1 + (year - 1) * 4 + (mdiff - 1) / 3
60-
return Period(ordin, freq=freq)
61-
6238
class Period(object):
6339

6440
__slots__ = ['freq', 'ordinal']
@@ -106,9 +82,6 @@ def __init__(self, value=None, freq=None, ordinal=None,
10682
if freq is None:
10783
raise ValueError("If value is None, freq cannot be None")
10884

109-
if year is None:
110-
raise ValueError("If value is None, year cannot be None")
111-
11285
self.ordinal = _ordinal_from_fields(year, month, quarter, day,
11386
hour, minute, second, freq)
11487

@@ -172,13 +145,16 @@ def __sub__(self, other):
172145
else: # pragma: no cover
173146
raise TypeError(other)
174147

175-
def asfreq(self, freq=None, how='E'):
148+
def asfreq(self, freq, how='E'):
176149
"""
150+
Convert Period to desired frequency, either at the start or end of the
151+
interval
177152
178153
Parameters
179154
----------
180-
freq :
181-
how :
155+
freq : string
156+
how : {'E', 'S', 'end', 'start'}, default 'end'
157+
Start or end of the timespan
182158
183159
Returns
184160
-------
@@ -220,17 +196,13 @@ def to_timestamp(self, freq=None, how='S'):
220196
-------
221197
Timestamp
222198
"""
223-
# how = _validate_end_alias(how)
224199
if freq is None:
225200
base, mult = _gfc(self.freq)
226201
new_val = self
227202
else:
228203
base, mult = _gfc(freq)
229204
new_val = self.asfreq(freq, how)
230205

231-
if mult != 1:
232-
raise ValueError('Only mult == 1 supported')
233-
234206
dt64 = plib.period_ordinal_to_dt64(new_val.ordinal, base)
235207
ts_freq = _period_rule_to_timestamp_rule(new_val.freq, how=how)
236208
return Timestamp(dt64, offset=to_offset(ts_freq))
@@ -424,7 +396,7 @@ def _get_date_and_freq(value, freq):
424396
elif reso == 'second':
425397
freq = 'S'
426398
else:
427-
raise ValueError("Could not infer frequency for period")
399+
raise ValueError("Invalid frequency or could not infer: %s" % reso)
428400

429401
return dt, freq
430402

@@ -444,11 +416,6 @@ def _period_unbox_array(arr, check=None):
444416
unboxer = np.frompyfunc(lambda x: _period_unbox(x, check=check), 1, 1)
445417
return unboxer(arr)
446418

447-
def _period_box_array(arr, freq):
448-
boxfunc = lambda x: Period(ordinal=x, freq=freq)
449-
boxer = np.frompyfunc(boxfunc, 1, 1)
450-
return boxer(arr)
451-
452419
def dt64arr_to_periodarr(data, freq):
453420
if data.dtype != np.dtype('M8[ns]'):
454421
raise ValueError('Wrong dtype: %s' % data.dtype)
@@ -479,7 +446,10 @@ def wrapper(self, other):
479446
return result
480447
return wrapper
481448

449+
482450
_INT64_DTYPE = np.dtype(np.int64)
451+
_NS_DTYPE = np.dtype('M8[ns]')
452+
483453

484454
class PeriodIndex(Int64Index):
485455
"""
@@ -730,12 +700,18 @@ def map(self, f):
730700
try:
731701
return f(self)
732702
except:
733-
values = np.asarray(list(self), dtype=object)
703+
values = self._get_object_array()
734704
return _algos.arrmap_object(values, f)
735705

706+
def _get_object_array(self):
707+
freq = self.freq
708+
boxfunc = lambda x: Period(ordinal=x, freq=freq)
709+
boxer = np.frompyfunc(boxfunc, 1, 1)
710+
return boxer(self.values)
711+
736712
def _mpl_repr(self):
737713
# how to represent ourselves to matplotlib
738-
return _period_box_array(self, self.freq)
714+
return self._get_object_array()
739715

740716
def to_timestamp(self, freq=None, how='start'):
741717
"""
@@ -758,9 +734,6 @@ def to_timestamp(self, freq=None, how='start'):
758734
base, mult = _gfc(freq)
759735
new_data = self.asfreq(freq, how)
760736

761-
if mult != 1:
762-
raise ValueError('Only mult == 1 supported')
763-
764737
new_data = plib.periodarr_to_dt64arr(new_data.values, base)
765738
return DatetimeIndex(new_data, freq='infer', name=self.name)
766739

@@ -823,14 +796,14 @@ def get_value(self, series, key):
823796
key = slice(pos[0], pos[1]+1)
824797
return series[key]
825798
else:
826-
key = to_period(asdt, freq=self.freq)
799+
key = Period(asdt, freq=self.freq)
827800
return self._engine.get_value(series, key.ordinal)
828801
except TypeError:
829802
pass
830803
except KeyError:
831804
pass
832805

833-
key = to_period(key, self.freq)
806+
key = Period(key, self.freq)
834807
return self._engine.get_value(series, key.ordinal)
835808

836809
def get_loc(self, key):
@@ -850,7 +823,7 @@ def get_loc(self, key):
850823
except TypeError:
851824
pass
852825

853-
key = to_period(key, self.freq).ordinal
826+
key = Period(key, self.freq).ordinal
854827
return self._engine.get_loc(key)
855828

856829
def join(self, other, how='left', level=None, return_indexers=False):
@@ -946,8 +919,10 @@ def _get_ordinal_range(start, end, periods, freq):
946919
if com._count_not_none(start, end, periods) < 2:
947920
raise ValueError('Must specify 2 of start, end, periods')
948921

949-
start = to_period(start, freq)
950-
end = to_period(end, freq)
922+
if start is not None:
923+
start = Period(start, freq)
924+
if end is not None:
925+
end = Period(end, freq)
951926

952927
is_start_per = isinstance(start, Period)
953928
is_end_per = isinstance(end, Period)

pandas/tseries/resample.py

+11-33
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ class TimeGrouper(CustomGrouper):
2222
rule : pandas offset string or object for identifying bin edges
2323
closed : closed end of interval; left (default) or right
2424
label : interval boundary to use for labeling; left (default) or right
25-
begin : optional, timestamp-like
26-
end : optional, timestamp-like
2725
nperiods : optional, integer
2826
convention : {'start', 'end', 'e', 's'}
2927
If axis is PeriodIndex
@@ -34,14 +32,12 @@ class TimeGrouper(CustomGrouper):
3432
directly from the associated object
3533
"""
3634
def __init__(self, freq='Min', closed='right', label='right', how='mean',
37-
begin=None, end=None, nperiods=None, axis=0,
35+
nperiods=None, axis=0,
3836
fill_method=None, limit=None, loffset=None, kind=None,
3937
convention=None, base=0):
4038
self.freq = freq
4139
self.closed = closed
4240
self.label = label
43-
self.begin = begin
44-
self.end = end
4541
self.nperiods = nperiods
4642
self.kind = kind
4743
self.convention = convention or 'E'
@@ -94,8 +90,8 @@ def _get_time_bins(self, axis):
9490
binner = labels = DatetimeIndex(data=[], freq=self.freq)
9591
return binner, [], labels
9692

97-
first, last = _get_range_edges(axis, self.begin, self.end, self.freq,
98-
closed=self.closed, base=self.base)
93+
first, last = _get_range_edges(axis, self.freq, closed=self.closed,
94+
base=self.base)
9995
binner = labels = DatetimeIndex(freq=self.freq, start=first, end=last)
10096

10197
# a little hack
@@ -156,9 +152,6 @@ def _get_time_period_bins(self, axis):
156152
end_stamps = (labels + 1).asfreq('D', 's').to_timestamp()
157153
bins = axis.searchsorted(end_stamps, side='left')
158154

159-
if bins[-1] < len(axis):
160-
bins = np.concatenate([bins, [len(axis)]])
161-
162155
return binner, bins, labels
163156

164157
def _resample_timestamps(self, obj):
@@ -212,12 +205,8 @@ def _resample_periods(self, obj):
212205

213206
if is_subperiod(axlabels.freq, self.freq):
214207
# Downsampling
215-
if len(memb) > 1:
216-
rng = np.arange(memb.values[0], memb.values[-1])
217-
bins = memb.searchsorted(rng, side='right')
218-
else:
219-
bins = np.array([], dtype=np.int32)
220-
208+
rng = np.arange(memb.values[0], memb.values[-1])
209+
bins = memb.searchsorted(rng, side='right')
221210
grouper = BinGrouper(bins, new_index)
222211

223212
grouped = obj.groupby(grouper, axis=self.axis)
@@ -255,34 +244,23 @@ def _take_new_index(obj, indexer, new_index, axis=0):
255244

256245

257246

258-
def _get_range_edges(axis, begin, end, offset, closed='left',
259-
base=0):
247+
def _get_range_edges(axis, offset, closed='left', base=0):
260248
if isinstance(offset, basestring):
261249
offset = to_offset(offset)
262250

263-
if not isinstance(offset, DateOffset):
264-
raise ValueError("Rule not a recognized offset")
265-
266251
if isinstance(offset, Tick):
267252
day_nanos = _delta_to_nanoseconds(timedelta(1))
268253
# #1165
269-
if ((day_nanos % offset.nanos) == 0 and begin is None
270-
and end is None):
254+
if (day_nanos % offset.nanos) == 0:
271255
return _adjust_dates_anchored(axis[0], axis[-1], offset,
272256
closed=closed, base=base)
273257

274-
if begin is None:
275-
if closed == 'left':
276-
first = Timestamp(offset.rollback(axis[0]))
277-
else:
278-
first = Timestamp(axis[0] - offset)
258+
if closed == 'left':
259+
first = Timestamp(offset.rollback(axis[0]))
279260
else:
280-
first = Timestamp(offset.rollback(begin))
261+
first = Timestamp(axis[0] - offset)
281262

282-
if end is None:
283-
last = Timestamp(axis[-1] + offset)
284-
else:
285-
last = Timestamp(offset.rollforward(end))
263+
last = Timestamp(axis[-1] + offset)
286264

287265
return first, last
288266

pandas/tseries/tests/test_period.py

+50-1
Original file line numberDiff line numberDiff line change
@@ -184,9 +184,13 @@ def test_strftime(self):
184184
'2000-01-01 12:34:12')
185185

186186
def test_sub_delta(self):
187-
result = Period('2011', freq='A') - Period('2007', freq='A')
187+
left, right = Period('2011', freq='A'), Period('2007', freq='A')
188+
result = left - right
188189
self.assertEqual(result, 4)
189190

191+
self.assertRaises(ValueError, left.__sub__,
192+
Period('2007-01', freq='M'))
193+
190194
def test_to_timestamp(self):
191195
p = Period('1982', freq='A')
192196
start_ts = p.to_timestamp(how='S')
@@ -234,6 +238,8 @@ def test_to_timestamp(self):
234238
result = p.to_timestamp('S', how='start')
235239
self.assertEquals(result, expected)
236240

241+
self.assertRaises(ValueError, p.to_timestamp, '5t')
242+
237243
def test_properties_annually(self):
238244
# Test properties on Periods with annually frequency.
239245
a_date = Period(freq='A', year=2007)
@@ -354,6 +360,39 @@ def test_constructor_corner(self):
354360
self.assertRaises(ValueError, Period, year=2007, month=1,
355361
freq='2M')
356362

363+
self.assertRaises(ValueError, Period, datetime.now())
364+
self.assertRaises(ValueError, Period, 1.6, freq='D')
365+
self.assertRaises(ValueError, Period, ordinal=1.6, freq='D')
366+
self.assertRaises(ValueError, Period, ordinal=2, value=1, freq='D')
367+
self.assertRaises(ValueError, Period)
368+
self.assertRaises(ValueError, Period, month=1)
369+
370+
p = Period('2007-01-01', freq='D')
371+
372+
result = Period(p, freq='A')
373+
exp = Period('2007', freq='A')
374+
self.assertEquals(result, exp)
375+
376+
def test_constructor_infer_freq(self):
377+
p = Period('2007-01-01')
378+
self.assert_(p.freq == 'D')
379+
380+
p = Period('2007-01-01 07')
381+
self.assert_(p.freq == 'H')
382+
383+
p = Period('2007-01-01 07:10')
384+
self.assert_(p.freq == 'T')
385+
386+
p = Period('2007-01-01 07:10:15')
387+
self.assert_(p.freq == 'S')
388+
389+
self.assertRaises(ValueError, Period, '2007-01-01 07:10:15.123456')
390+
391+
def test_comparisons(self):
392+
p = Period('2007-01-01')
393+
self.assertEquals(p, p)
394+
self.assert_(not p == 1)
395+
357396
def noWrap(item):
358397
return item
359398

@@ -363,6 +402,10 @@ class TestFreqConversion(TestCase):
363402
def __init__(self, *args, **kwds):
364403
TestCase.__init__(self, *args, **kwds)
365404

405+
def test_asfreq_corner(self):
406+
val = Period(freq='A', year=2007)
407+
self.assertRaises(ValueError, val.asfreq, '5t')
408+
366409
def test_conv_annual(self):
367410
# frequency conversion tests: from Annual Frequency
368411

@@ -1039,6 +1082,12 @@ def test_constructor_fromarraylike(self):
10391082
exp = idx.asfreq('D', 'e')
10401083
self.assert_(result.equals(exp))
10411084

1085+
def test_constructor_datetime64arr(self):
1086+
vals = np.arange(100000, 100000 + 10000, 100, dtype=np.int64)
1087+
vals = vals.view(np.dtype('M8[us]'))
1088+
1089+
self.assertRaises(ValueError, PeriodIndex, vals, freq='D')
1090+
10421091
def test_comp_period(self):
10431092
idx = period_range('2007-01', periods=20, freq='M')
10441093

0 commit comments

Comments
 (0)