From 6752c144053e0e4544396541661c846ae1759a76 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 3 May 2020 17:02:32 -0700 Subject: [PATCH] PERF: 30% faster is_period_object checks --- pandas/_libs/lib.pyx | 9 +++++---- pandas/_libs/tslibs/period.pxd | 1 + pandas/_libs/tslibs/period.pyx | 10 +++++++++- 3 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 pandas/_libs/tslibs/period.pxd diff --git a/pandas/_libs/lib.pyx b/pandas/_libs/lib.pyx index e3b1e1ec8cb6a..f844ad45c7026 100644 --- a/pandas/_libs/lib.pyx +++ b/pandas/_libs/lib.pyx @@ -75,6 +75,7 @@ from pandas._libs.tslibs.nattype cimport ( from pandas._libs.tslibs.conversion cimport convert_to_tsobject from pandas._libs.tslibs.timedeltas cimport convert_to_timedelta64 from pandas._libs.tslibs.timezones cimport get_timezone, tz_compare +from pandas._libs.tslibs.period cimport is_period_object from pandas._libs.missing cimport ( checknull, @@ -185,7 +186,7 @@ def is_scalar(val: object) -> bool: # Note: PyNumber_Check check includes Decimal, Fraction, numbers.Number return (PyNumber_Check(val) - or util.is_period_object(val) + or is_period_object(val) or is_interval(val) or util.is_offset_object(val)) @@ -942,7 +943,7 @@ def is_period(val: object) -> bool: ------- bool """ - return util.is_period_object(val) + return is_period_object(val) def is_list_like(obj: object, allow_sets: bool = True) -> bool: @@ -1417,7 +1418,7 @@ def infer_dtype(value: object, skipna: bool = True) -> str: if is_bytes_array(values, skipna=skipna): return "bytes" - elif util.is_period_object(val): + elif is_period_object(val): if is_period_array(values): return "period" @@ -1849,7 +1850,7 @@ cpdef bint is_time_array(ndarray values, bint skipna=False): cdef class PeriodValidator(TemporalValidator): cdef inline bint is_value_typed(self, object value) except -1: - return util.is_period_object(value) + return is_period_object(value) cdef inline bint is_valid_null(self, object value) except -1: return checknull_with_nat(value) diff --git a/pandas/_libs/tslibs/period.pxd b/pandas/_libs/tslibs/period.pxd new file mode 100644 index 0000000000000..eb11a4a572e85 --- /dev/null +++ b/pandas/_libs/tslibs/period.pxd @@ -0,0 +1 @@ +cdef bint is_period_object(object obj) diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 5cf8fedbf0431..878dbcfd99842 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -36,7 +36,6 @@ cdef extern from "src/datetime/np_datetime.h": npy_datetimestruct *d) nogil cimport pandas._libs.tslibs.util as util -from pandas._libs.tslibs.util cimport is_period_object from pandas._libs.tslibs.timestamps import Timestamp from pandas._libs.tslibs.timezones cimport is_utc, is_tzlocal, get_dst_info @@ -2467,6 +2466,15 @@ class Period(_Period): return cls._from_ordinal(ordinal, freq) +cdef bint is_period_object(object obj): + """ + Cython-optimized equivalent of isinstance(obj, Period) + """ + # Note: this is significantly faster than the implementation in tslibs.util, + # only use the util version when necessary to prevent circular imports. + return isinstance(obj, _Period) + + cdef int64_t _ordinal_from_fields(int year, int month, quarter, int day, int hour, int minute, int second, freq): base, mult = get_freq_code(freq)