Skip to content

Commit 56051cf

Browse files
committed
REF: remove period multipliers, close #1199
1 parent 1082362 commit 56051cf

File tree

4 files changed

+63
-64
lines changed

4 files changed

+63
-64
lines changed

pandas/src/datetime.pyx

+17-35
Original file line numberDiff line numberDiff line change
@@ -1233,7 +1233,7 @@ cdef inline int64_t remove_mult(int64_t period_ord_w_mult, int64_t mult):
12331233

12341234
return period_ord_w_mult * mult + 1;
12351235

1236-
def dt64arr_to_periodarr(ndarray[int64_t] dtarr, int freq, int64_t mult):
1236+
def dt64arr_to_periodarr(ndarray[int64_t] dtarr, int freq):
12371237
"""
12381238
Convert array of datetime64 values (passed in as 'i8' dtype) to a set of
12391239
periods corresponding to desired frequency, per period convention.
@@ -1251,10 +1251,9 @@ def dt64arr_to_periodarr(ndarray[int64_t] dtarr, int freq, int64_t mult):
12511251
PyArray_DatetimeToDatetimeStruct(dtarr[i], NPY_FR_us, &dts)
12521252
out[i] = get_period_ordinal(dts.year, dts.month, dts.day,
12531253
dts.hour, dts.min, dts.sec, freq)
1254-
out[i] = apply_mult(out[i], mult)
12551254
return out
12561255

1257-
def periodarr_to_dt64arr(ndarray[int64_t] periodarr, int freq, int64_t mult):
1256+
def periodarr_to_dt64arr(ndarray[int64_t] periodarr, int freq):
12581257
"""
12591258
Convert array to datetime64 values from a set of ordinals corresponding to
12601259
periods per period convention.
@@ -1268,40 +1267,33 @@ def periodarr_to_dt64arr(ndarray[int64_t] periodarr, int freq, int64_t mult):
12681267
out = np.empty(l, dtype='i8')
12691268

12701269
for i in range(l):
1271-
out[i] = period_ordinal_to_dt64(periodarr[i], freq, mult)
1270+
out[i] = period_ordinal_to_dt64(periodarr[i], freq)
12721271

12731272
return out
12741273

12751274
cdef char START = 'S'
12761275
cdef char END = 'E'
12771276

1278-
cpdef int64_t period_asfreq(int64_t period_ordinal, int freq1, int64_t mult1,
1279-
int freq2, int64_t mult2, bint end):
1277+
cpdef int64_t period_asfreq(int64_t period_ordinal, int freq1, int freq2,
1278+
bint end):
12801279
"""
12811280
Convert period ordinal from one frequency to another, and if upsampling,
12821281
choose to use start ('S') or end ('E') of period.
12831282
"""
12841283
cdef:
12851284
int64_t retval
12861285

1287-
period_ordinal = remove_mult(period_ordinal, mult1)
1288-
1289-
if mult1 != 1 and end:
1290-
period_ordinal += (mult1 - 1)
1291-
12921286
if end:
12931287
retval = asfreq(period_ordinal, freq1, freq2, END)
12941288
else:
12951289
retval = asfreq(period_ordinal, freq1, freq2, START)
1296-
retval = apply_mult(retval, mult2)
12971290

12981291
if retval == INT32_MIN:
12991292
raise ValueError('Frequency conversion failed')
13001293

13011294
return retval
13021295

1303-
def period_asfreq_arr(ndarray[int64_t] arr, int freq1, int64_t mult1,
1304-
int freq2, int64_t mult2, bint end):
1296+
def period_asfreq_arr(ndarray[int64_t] arr, int freq1, int freq2, bint end):
13051297
"""
13061298
Convert int64-array of period ordinals from one frequency to another, and
13071299
if upsampling, choose to use start ('S') or end ('E') of period.
@@ -1326,32 +1318,25 @@ def period_asfreq_arr(ndarray[int64_t] arr, int freq1, int64_t mult1,
13261318
relation = START
13271319

13281320
for i in range(n):
1329-
ordinal = remove_mult(arr[i], mult1)
13301321
val = func(arr[i], relation, &finfo)
13311322
if val == -1:
13321323
raise ValueError("Unable to convert to desired frequency.")
1333-
result[i] = apply_mult(val, mult2)
1324+
result[i] = val
13341325

13351326
return result
13361327

1337-
def period_ordinal(int y, int m, int d, int h, int min, int s,
1338-
int freq, int64_t mult):
1328+
def period_ordinal(int y, int m, int d, int h, int min, int s, int freq):
13391329
cdef:
13401330
int64_t ordinal
13411331

1342-
ordinal = get_period_ordinal(y, m, d, h, min, s, freq)
1332+
return get_period_ordinal(y, m, d, h, min, s, freq)
13431333

1344-
return apply_mult(ordinal, mult)
13451334

1346-
cpdef int64_t period_ordinal_to_dt64(int64_t period_ordinal, int freq,
1347-
int64_t mult):
1335+
cpdef int64_t period_ordinal_to_dt64(int64_t ordinal, int freq):
13481336
cdef:
1349-
int64_t ordinal
13501337
npy_datetimestruct dts
13511338
date_info dinfo
13521339

1353-
ordinal = remove_mult(period_ordinal, mult)
1354-
13551340
get_date_info(ordinal, freq, &dinfo)
13561341

13571342
dts.year = dinfo.year
@@ -1364,22 +1349,21 @@ cpdef int64_t period_ordinal_to_dt64(int64_t period_ordinal, int freq,
13641349

13651350
return PyArray_DatetimeStructToDatetime(NPY_FR_us, &dts)
13661351

1367-
def period_ordinal_to_string(int64_t value, int freq, int64_t mult):
1352+
def period_ordinal_to_string(int64_t value, int freq):
13681353
cdef:
13691354
char *ptr
13701355

1371-
ptr = period_to_string(remove_mult(value, mult), freq)
1356+
ptr = period_to_string(value, freq)
13721357

13731358
if ptr == NULL:
13741359
raise ValueError("Could not create string from ordinal '%s'" % value)
13751360

13761361
return <object> ptr
13771362

1378-
def period_strftime(int64_t value, int freq, int64_t mult, object fmt):
1363+
def period_strftime(int64_t value, int freq, object fmt):
13791364
cdef:
13801365
char *ptr
13811366

1382-
value = remove_mult(value, mult)
13831367
ptr = period_to_string2(value, freq, <char*>fmt)
13841368

13851369
if ptr == NULL:
@@ -1391,13 +1375,11 @@ def period_strftime(int64_t value, int freq, int64_t mult, object fmt):
13911375

13921376
ctypedef int (*accessor)(int64_t ordinal, int freq) except INT32_MIN
13931377

1394-
def get_period_field(int code, int64_t value, int freq,
1395-
int64_t mult):
1378+
def get_period_field(int code, int64_t value, int freq):
13961379
cdef accessor f = _get_accessor_func(code)
1397-
return f(remove_mult(value, mult), freq)
1380+
return f(value, freq)
13981381

1399-
def get_period_field_arr(int code, ndarray[int64_t] arr,
1400-
int freq, int64_t mult):
1382+
def get_period_field_arr(int code, ndarray[int64_t] arr, int freq):
14011383
cdef:
14021384
Py_ssize_t i, sz
14031385
ndarray[int64_t] out
@@ -1409,7 +1391,7 @@ def get_period_field_arr(int code, ndarray[int64_t] arr,
14091391
out = np.empty(sz, dtype=np.int64)
14101392

14111393
for i in range(sz):
1412-
out[i] = f(remove_mult(arr[i], mult), freq)
1394+
out[i] = f(arr[i], freq)
14131395

14141396
return out
14151397

pandas/tseries/frequencies.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def get_freq_code(freqstr):
6868
return code, stride
6969

7070

71-
def _get_freq_str(base, mult):
71+
def _get_freq_str(base, mult=1):
7272
code = _reverse_period_code_map.get(base)
7373
if code is None:
7474
return _unknown_freq

pandas/tseries/period.py

+37-25
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def _period_field_accessor(name, alias=None):
2424
alias = name
2525
def f(self):
2626
base, mult = _gfc(self.freq)
27-
return lib.get_period_field(alias, self.ordinal, base, mult)
27+
return lib.get_period_field(alias, self.ordinal, base)
2828
f.__name__ = name
2929
return property(f)
3030

@@ -33,7 +33,7 @@ def _field_accessor(name, alias=None):
3333
alias = name
3434
def f(self):
3535
base, mult = _gfc(self.freq)
36-
return lib.get_period_field_arr(alias, self.values, base, mult)
36+
return lib.get_period_field_arr(alias, self.values, base)
3737
f.__name__ = name
3838
return property(f)
3939

@@ -108,6 +108,8 @@ def __init__(self, value=None, freq=None, ordinal=None,
108108
raise ValueError("If value is None, year cannot be None")
109109

110110
base, mult = _gfc(freq)
111+
if mult != 1:
112+
raise ValueError('Only mult == 1 supported')
111113

112114
if quarter is not None:
113115
mnum = _month_numbers[_freq_mod._get_rule_month(freq)] + 1
@@ -116,7 +118,7 @@ def __init__(self, value=None, freq=None, ordinal=None,
116118
year -= 1
117119

118120
self.ordinal = lib.period_ordinal(year, month, day, hour, minute,
119-
second, base, mult)
121+
second, base)
120122

121123
elif isinstance(value, Period):
122124
other = value
@@ -163,12 +165,15 @@ def __init__(self, value=None, freq=None, ordinal=None,
163165
raise ValueError(msg)
164166

165167
base, mult = _gfc(freq)
168+
if mult != 1:
169+
raise ValueError('Only mult == 1 supported')
166170

167171
if self.ordinal is None:
168-
self.ordinal = lib.period_ordinal(dt.year, dt.month, dt.day, dt.hour,
169-
dt.minute, dt.second, base, mult)
172+
self.ordinal = lib.period_ordinal(dt.year, dt.month, dt.day,
173+
dt.hour, dt.minute, dt.second,
174+
base)
170175

171-
self.freq = _freq_mod._get_freq_str(base, mult)
176+
self.freq = _freq_mod._get_freq_str(base)
172177

173178
def __eq__(self, other):
174179
if isinstance(other, Period):
@@ -210,14 +215,16 @@ def asfreq(self, freq=None, how='E'):
210215
base1, mult1 = _gfc(self.freq)
211216
base2, mult2 = _gfc(freq)
212217

218+
if mult2 != 1:
219+
raise ValueError('Only mult == 1 supported')
220+
213221
if how not in ('S', 'E'):
214222
raise ValueError('relation argument must be one of S or E')
215223

216224
end = how == 'E'
217-
new_ordinal = lib.period_asfreq(self.ordinal, base1, mult1,
218-
base2, mult2, end)
225+
new_ordinal = lib.period_asfreq(self.ordinal, base1, base2, end)
219226

220-
return Period(ordinal=new_ordinal, freq=(base2, mult2))
227+
return Period(ordinal=new_ordinal, freq=base2)
221228

222229
@property
223230
def start_time(self):
@@ -250,7 +257,11 @@ def to_timestamp(self, freq=None, how='S'):
250257
else:
251258
base, mult = _gfc(freq)
252259
new_val = self.asfreq(freq, how)
253-
dt64 = lib.period_ordinal_to_dt64(new_val.ordinal, base, mult)
260+
261+
if mult != 1:
262+
raise ValueError('Only mult == 1 supported')
263+
264+
dt64 = lib.period_ordinal_to_dt64(new_val.ordinal, base)
254265
ts_freq = _period_rule_to_timestamp_rule(new_val.freq, how=how)
255266
return Timestamp(dt64, offset=to_offset(ts_freq))
256267

@@ -274,15 +285,13 @@ def now(cls, freq=None):
274285

275286
def __repr__(self):
276287
base, mult = _gfc(self.freq)
277-
formatted = lib.period_ordinal_to_string(self.ordinal, base, mult)
288+
formatted = lib.period_ordinal_to_string(self.ordinal, base)
278289
freqstr = _freq_mod._reverse_period_code_map[base]
279-
if mult == 1:
280-
return "Period('%s', '%s')" % (formatted, freqstr)
281-
return ("Period('%s', '%d%s')" % (formatted, mult, freqstr))
290+
return "Period('%s', '%s')" % (formatted, freqstr)
282291

283292
def __str__(self):
284293
base, mult = _gfc(self.freq)
285-
formatted = lib.period_ordinal_to_string(self.ordinal, base, mult)
294+
formatted = lib.period_ordinal_to_string(self.ordinal, base)
286295
return ("%s" % formatted)
287296

288297
def strftime(self, fmt):
@@ -424,9 +433,9 @@ def strftime(self, fmt):
424433
"""
425434
base, mult = _gfc(self.freq)
426435
if fmt is not None:
427-
return lib.period_strftime(self.ordinal, base, mult, fmt)
436+
return lib.period_strftime(self.ordinal, base, fmt)
428437
else:
429-
return lib.period_ordinal_to_string(self.ordinal, base, mult)
438+
return lib.period_ordinal_to_string(self.ordinal, base)
430439

431440
def _period_unbox(key, check=None):
432441
'''
@@ -465,7 +474,7 @@ def dt64arr_to_periodarr(data, freq):
465474
else:
466475
base, mult = freq
467476

468-
return lib.dt64arr_to_periodarr(data.view('i8'), base, mult)
477+
return lib.dt64arr_to_periodarr(data.view('i8'), base)
469478

470479
# --- Period index sketch
471480

@@ -589,8 +598,7 @@ def __new__(cls, data=None,
589598
else:
590599
base1, mult1 = _gfc(data.freq)
591600
base2, mult2 = _gfc(freq)
592-
data = lib.period_asfreq_arr(data.values, base1, mult1,
593-
base2, mult2, 1)
601+
data = lib.period_asfreq_arr(data.values, base1, base2, 1)
594602
else:
595603
if freq is None and len(data) > 0:
596604
freq = getattr(data[0], 'freq')
@@ -664,12 +672,14 @@ def asfreq(self, freq=None, how='E'):
664672
else:
665673
base2, mult2 = freq
666674

675+
if mult2 != 1:
676+
raise ValueError('Only mult == 1 supported')
677+
667678
if how not in ('S', 'E'):
668679
raise ValueError('relation argument must be one of S or E')
669680

670681
end = how == 'E'
671-
new_data = lib.period_asfreq_arr(self.values, base1, mult1,
672-
base2, mult2, end)
682+
new_data = lib.period_asfreq_arr(self.values, base1, base2, end)
673683

674684
result = new_data.view(PeriodIndex)
675685
result.name = self.name
@@ -719,12 +729,14 @@ def to_timestamp(self, freq=None, how='start'):
719729
if freq is None:
720730
base, mult = _gfc(self.freq)
721731
new_data = self
722-
# freq = self.freq
723732
else:
724733
base, mult = _gfc(freq)
725734
new_data = self.asfreq(freq, how)
726-
# freq = 'infer'
727-
new_data = lib.periodarr_to_dt64arr(new_data.values, base, mult)
735+
736+
if mult != 1:
737+
raise ValueError('Only mult == 1 supported')
738+
739+
new_data = lib.periodarr_to_dt64arr(new_data.values, base)
728740
return DatetimeIndex(new_data, freq='infer')
729741

730742
def shift(self, n):

pandas/tseries/tests/test_period.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,6 @@ def test_freq_str(self):
153153
i1 = Period('1982', freq='Min')
154154
self.assert_(i1.freq[0] != '1')
155155

156-
i2 = Period('11/30/2005', freq='2Q')
157-
self.assertEquals(i2.freq[0], '2')
158-
159156
def test_to_timestamp(self):
160157
p = Period('1982', freq='A')
161158
start_ts = p.to_timestamp(how='S')
@@ -1304,6 +1301,14 @@ def test_to_period_quarterly(self):
13041301
result = stamps.to_period(freq)
13051302
self.assert_(rng.equals(result))
13061303

1304+
def test_no_multiples(self):
1305+
self.assertRaises(ValueError, period_range, '1989Q3', periods=10,
1306+
freq='2Q')
1307+
1308+
self.assertRaises(ValueError, period_range, '1989', periods=10,
1309+
freq='2A')
1310+
self.assertRaises(ValueError, Period, '1989', freq='2A')
1311+
13071312
# def test_iindex_multiples(self):
13081313
# ii = PeriodIndex(start='1/1/10', end='12/31/12', freq='2M')
13091314
# self.assertEquals(ii[0], Period('1/1/10', '2M'))

0 commit comments

Comments
 (0)