Skip to content

Commit fec1b51

Browse files
committed
Fix performance issues when creating multiple instances of Period (pandas-dev#12903, pandas-dev#11831)
1 parent 6c692ae commit fec1b51

File tree

3 files changed

+21
-31
lines changed

3 files changed

+21
-31
lines changed

pandas/src/period.pyx

+7-24
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ from tslib cimport (
3636
_nat_scalar_rules,
3737
)
3838

39+
from pandas.tseries.frequencies import _period_alias_dict
40+
from pandas.tseries.frequencies import _get_freq_str
41+
from pandas.tseries.frequencies import to_offset
42+
from pandas.tseries.frequencies import get_freq_code as _gfc
43+
from pandas.tseries import frequencies
44+
from pandas.tseries.constants import US_RESO, MS_RESO, S_RESO, T_RESO, H_RESO, D_RESO
45+
3946
from sys import version_info
4047

4148
cdef bint PY2 = version_info[0] == 2
@@ -476,12 +483,6 @@ cpdef resolution(ndarray[int64_t] stamps, tz=None):
476483
reso = curr_reso
477484
return reso
478485

479-
US_RESO = 0
480-
MS_RESO = 1
481-
S_RESO = 2
482-
T_RESO = 3
483-
H_RESO = 4
484-
D_RESO = 5
485486

486487
cdef inline int _reso_stamp(pandas_datetimestruct *dts):
487488
if dts.us != 0:
@@ -662,16 +663,12 @@ cdef class Period(object):
662663
def _maybe_convert_freq(cls, object freq):
663664

664665
if isinstance(freq, compat.string_types):
665-
from pandas.tseries.frequencies import _period_alias_dict
666666
freq = freq.upper()
667667
freq = _period_alias_dict.get(freq, freq)
668668
elif isinstance(freq, (int, tuple)):
669-
from pandas.tseries.frequencies import get_freq_code as _gfc
670-
from pandas.tseries.frequencies import _get_freq_str
671669
code, stride = _gfc(freq)
672670
freq = _get_freq_str(code, stride)
673671

674-
from pandas.tseries.frequencies import to_offset
675672
freq = to_offset(freq)
676673

677674
if freq.n <= 0:
@@ -691,9 +688,6 @@ cdef class Period(object):
691688
def __init__(self, value=None, freq=None, ordinal=None,
692689
year=None, month=1, quarter=None, day=1,
693690
hour=0, minute=0, second=0):
694-
from pandas.tseries import frequencies
695-
from pandas.tseries.frequencies import get_freq_code as _gfc
696-
697691
# freq points to a tuple (base, mult); base is one of the defined
698692
# periods such as A, Q, etc. Every five minutes would be, e.g.,
699693
# ('T', 5) but may be passed in as a string like '5T'
@@ -771,7 +765,6 @@ cdef class Period(object):
771765

772766
def __richcmp__(self, other, op):
773767
if isinstance(other, Period):
774-
from pandas.tseries.frequencies import get_freq_code as _gfc
775768
if other.freq != self.freq:
776769
msg = _DIFFERENT_FREQ.format(self.freqstr, other.freqstr)
777770
raise IncompatibleFrequency(msg)
@@ -790,7 +783,6 @@ cdef class Period(object):
790783
return hash((self.ordinal, self.freq))
791784

792785
def _add_delta(self, other):
793-
from pandas.tseries import frequencies
794786
if isinstance(other, (timedelta, np.timedelta64, offsets.Tick, Timedelta)):
795787
offset = frequencies.to_offset(self.freq.rule_code)
796788
if isinstance(offset, offsets.Tick):
@@ -868,7 +860,6 @@ cdef class Period(object):
868860
-------
869861
resampled : Period
870862
"""
871-
from pandas.tseries.frequencies import get_freq_code as _gfc
872863
how = _validate_end_alias(how)
873864
base1, mult1 = _gfc(self.freq)
874865
base2, mult2 = _gfc(freq)
@@ -918,8 +909,6 @@ cdef class Period(object):
918909
-------
919910
Timestamp
920911
"""
921-
from pandas.tseries import frequencies
922-
from pandas.tseries.frequencies import get_freq_code as _gfc
923912
how = _validate_end_alias(how)
924913

925914
if freq is None:
@@ -933,7 +922,6 @@ cdef class Period(object):
933922
return Timestamp(dt64, tz=tz)
934923

935924
cdef _field(self, alias):
936-
from pandas.tseries.frequencies import get_freq_code as _gfc
937925
base, mult = _gfc(self.freq)
938926
return get_period_field(alias, self.ordinal, base)
939927

@@ -996,7 +984,6 @@ cdef class Period(object):
996984
return self.freq.freqstr
997985

998986
def __repr__(self):
999-
from pandas.tseries.frequencies import get_freq_code as _gfc
1000987
base, mult = _gfc(self.freq)
1001988
formatted = period_format(self.ordinal, base)
1002989
return "Period('%s', '%s')" % (formatted, self.freqstr)
@@ -1008,7 +995,6 @@ cdef class Period(object):
1008995
Invoked by unicode(df) in py2 only. Yields a Unicode String in both
1009996
py2/py3.
1010997
"""
1011-
from pandas.tseries.frequencies import get_freq_code as _gfc
1012998
base, mult = _gfc(self.freq)
1013999
formatted = period_format(self.ordinal, base)
10141000
value = ("%s" % formatted)
@@ -1159,14 +1145,12 @@ cdef class Period(object):
11591145
>>> a.strftime('%b. %d, %Y was a %A')
11601146
'Jan. 01, 2001 was a Monday'
11611147
"""
1162-
from pandas.tseries.frequencies import get_freq_code as _gfc
11631148
base, mult = _gfc(self.freq)
11641149
return period_format(self.ordinal, base, fmt)
11651150

11661151

11671152
def _ordinal_from_fields(year, month, quarter, day, hour, minute,
11681153
second, freq):
1169-
from pandas.tseries.frequencies import get_freq_code as _gfc
11701154
base, mult = _gfc(freq)
11711155
if quarter is not None:
11721156
year, month = _quarter_to_myear(year, quarter, freq)
@@ -1179,7 +1163,6 @@ def _quarter_to_myear(year, quarter, freq):
11791163
if quarter <= 0 or quarter > 4:
11801164
raise ValueError('Quarter must be 1 <= q <= 4')
11811165

1182-
from pandas.tseries import frequencies
11831166
mnum = frequencies._month_numbers[frequencies._get_rule_month(freq)] + 1
11841167
month = (mnum + (quarter - 1) * 3) % 12 + 1
11851168
if month > mnum:

pandas/tseries/constants.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
US_RESO = 0
2+
MS_RESO = 1
3+
S_RESO = 2
4+
T_RESO = 3
5+
H_RESO = 4
6+
D_RESO = 5
7+

pandas/tseries/frequencies.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import pandas.core.common as com
1515
import pandas.lib as lib
1616
import pandas.tslib as tslib
17-
import pandas._period as period
17+
from pandas.tseries import constants
1818
from pandas.tslib import Timedelta
1919
from pytz import AmbiguousTimeError
2020

@@ -38,12 +38,12 @@ class Resolution(object):
3838

3939
# defined in period.pyx
4040
# note that these are different from freq codes
41-
RESO_US = period.US_RESO
42-
RESO_MS = period.MS_RESO
43-
RESO_SEC = period.S_RESO
44-
RESO_MIN = period.T_RESO
45-
RESO_HR = period.H_RESO
46-
RESO_DAY = period.D_RESO
41+
RESO_US = constants.US_RESO
42+
RESO_MS = constants.MS_RESO
43+
RESO_SEC = constants.S_RESO
44+
RESO_MIN = constants.T_RESO
45+
RESO_HR = constants.H_RESO
46+
RESO_DAY = constants.D_RESO
4747

4848
_reso_str_map = {
4949
RESO_US: 'microsecond',

0 commit comments

Comments
 (0)