Skip to content

Commit 6747ab5

Browse files
jbrockmendeljreback
authored andcommitted
implement is_offsetlike (#18823)
1 parent 852c53e commit 6747ab5

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

pandas/core/dtypes/common.py

+33-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from .generic import (ABCCategorical, ABCPeriodIndex,
1313
ABCDatetimeIndex, ABCSeries,
1414
ABCSparseArray, ABCSparseSeries, ABCCategoricalIndex,
15-
ABCIndexClass)
16-
from .inference import is_string_like
15+
ABCIndexClass, ABCDateOffset)
16+
from .inference import is_string_like, is_list_like
1717
from .inference import * # noqa
1818

1919

@@ -266,6 +266,37 @@ def is_datetimetz(arr):
266266
is_datetime64tz_dtype(arr))
267267

268268

269+
def is_offsetlike(arr_or_obj):
270+
"""
271+
Check if obj or all elements of list-like is DateOffset
272+
273+
Parameters
274+
----------
275+
arr_or_obj : object
276+
277+
Returns
278+
-------
279+
boolean : Whether the object is a DateOffset or listlike of DatetOffsets
280+
281+
Examples
282+
--------
283+
>>> is_offsetlike(pd.DateOffset(days=1))
284+
True
285+
>>> is_offsetlike('offset')
286+
False
287+
>>> is_offsetlike([pd.offsets.Minute(4), pd.offsets.MonthEnd()])
288+
True
289+
>>> is_offsetlike(np.array([pd.DateOffset(months=3), pd.Timestamp.now()]))
290+
False
291+
"""
292+
if isinstance(arr_or_obj, ABCDateOffset):
293+
return True
294+
elif (is_list_like(arr_or_obj) and len(arr_or_obj) and
295+
is_object_dtype(arr_or_obj)):
296+
return all(isinstance(x, ABCDateOffset) for x in arr_or_obj)
297+
return False
298+
299+
269300
def is_period(arr):
270301
"""
271302
Check whether an array-like is a periodical index.

pandas/core/ops.py

+5-15
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,15 @@
3030
is_object_dtype, is_timedelta64_dtype,
3131
is_datetime64_dtype, is_datetime64tz_dtype,
3232
is_bool_dtype, is_datetimetz,
33-
is_list_like,
33+
is_list_like, is_offsetlike,
3434
is_scalar,
3535
_ensure_object)
3636
from pandas.core.dtypes.cast import maybe_upcast_putmask, find_common_type
3737
from pandas.core.dtypes.generic import (
3838
ABCSeries,
3939
ABCDataFrame,
4040
ABCIndex,
41-
ABCPeriodIndex,
42-
ABCDateOffset)
41+
ABCPeriodIndex)
4342

4443
# -----------------------------------------------------------------------------
4544
# Functions that add arithmetic methods to objects, given arithmetic factory
@@ -363,7 +362,7 @@ def __init__(self, left, right, name, na_op):
363362
rvalues = self._convert_to_array(right, name=name, other=lvalues)
364363

365364
# left
366-
self.is_offset_lhs = self._is_offset(left)
365+
self.is_offset_lhs = is_offsetlike(left)
367366
self.is_timedelta_lhs = is_timedelta64_dtype(lvalues)
368367
self.is_datetime64_lhs = is_datetime64_dtype(lvalues)
369368
self.is_datetime64tz_lhs = is_datetime64tz_dtype(lvalues)
@@ -373,7 +372,7 @@ def __init__(self, left, right, name, na_op):
373372
self.is_floating_lhs = left.dtype.kind == 'f'
374373

375374
# right
376-
self.is_offset_rhs = self._is_offset(right)
375+
self.is_offset_rhs = is_offsetlike(right)
377376
self.is_datetime64_rhs = is_datetime64_dtype(rvalues)
378377
self.is_datetime64tz_rhs = is_datetime64tz_dtype(rvalues)
379378
self.is_datetime_rhs = (self.is_datetime64_rhs or
@@ -515,7 +514,7 @@ def _convert_to_array(self, values, name=None, other=None):
515514
values = np.empty(values.shape, dtype=other.dtype)
516515
values[:] = iNaT
517516
return values
518-
elif self._is_offset(values):
517+
elif is_offsetlike(values):
519518
return values
520519
else:
521520
raise TypeError("incompatible type [{dtype}] for a "
@@ -618,15 +617,6 @@ def f(x):
618617

619618
return lvalues, rvalues
620619

621-
def _is_offset(self, arr_or_obj):
622-
""" check if obj or all elements of list-like is DateOffset """
623-
if isinstance(arr_or_obj, ABCDateOffset):
624-
return True
625-
elif (is_list_like(arr_or_obj) and len(arr_or_obj) and
626-
is_object_dtype(arr_or_obj)):
627-
return all(isinstance(x, ABCDateOffset) for x in arr_or_obj)
628-
return False
629-
630620

631621
def _align_method_SERIES(left, right, align_asobject=False):
632622
""" align lhs and rhs Series """

pandas/tests/dtypes/test_common.py

+13
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,19 @@ def test_is_complex_dtype():
537537
assert com.is_complex_dtype(np.array([1 + 1j, 5]))
538538

539539

540+
def test_is_offsetlike():
541+
assert com.is_offsetlike(np.array([pd.DateOffset(month=3),
542+
pd.offsets.Nano()]))
543+
assert com.is_offsetlike(pd.offsets.MonthEnd())
544+
assert com.is_offsetlike(pd.Index([pd.DateOffset(second=1)]))
545+
546+
assert not com.is_offsetlike(pd.Timedelta(1))
547+
assert not com.is_offsetlike(np.array([1 + 1j, 5]))
548+
549+
# mixed case
550+
assert not com.is_offsetlike(np.array([pd.DateOffset(), pd.Timestamp(0)]))
551+
552+
540553
@pytest.mark.parametrize('input_param,result', [
541554
(int, np.dtype(int)),
542555
('int32', np.dtype('int32')),

0 commit comments

Comments
 (0)