Skip to content

Commit f51c131

Browse files
jbrockmendeljreback
authored andcommitted
BUG: TDI/PI comparison with zero-dim array (#26707)
1 parent 5b10e31 commit f51c131

File tree

6 files changed

+40
-0
lines changed

6 files changed

+40
-0
lines changed

doc/source/whatsnew/v0.25.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -539,13 +539,15 @@ Datetimelike
539539
- Bug in adding :class:`DateOffset` with nonzero month to :class:`DatetimeIndex` would raise ``ValueError`` (:issue:`26258`)
540540
- Bug in :func:`to_datetime` which raises unhandled ``OverflowError`` when called with mix of invalid dates and ``NaN`` values with ``format='%Y%m%d'`` and ``error='coerce'`` (:issue:`25512`)
541541
- Bug in :func:`to_datetime` which raises ``TypeError`` for ``format='%Y%m%d'`` when called for invalid integer dates with length >= 6 digits with ``errors='ignore'``
542+
- Bug when comparing a :class:`PeriodIndex` against a zero-dimensional numpy array (:issue:`26689`)
542543

543544
Timedelta
544545
^^^^^^^^^
545546

546547
- Bug in :func:`TimedeltaIndex.intersection` where for non-monotonic indices in some cases an empty ``Index`` was returned when in fact an intersection existed (:issue:`25913`)
547548
- Bug with comparisons between :class:`Timedelta` and ``NaT`` raising ``TypeError`` (:issue:`26039`)
548549
- Bug when adding or subtracting a :class:`BusinessHour` to a :class:`Timestamp` with the resulting time landing in a following or prior day respectively (:issue:`26381`)
550+
- Bug when comparing a :class:`TimedeltaIndex` against a zero-dimensional numpy array (:issue:`26689`)
549551

550552
Timezones
551553
^^^^^^^^^

pandas/core/arrays/period.py

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import numpy as np
66

7+
from pandas._libs import lib
78
from pandas._libs.tslibs import (
89
NaT, NaTType, frequencies as libfrequencies, iNaT, period as libperiod)
910
from pandas._libs.tslibs.fields import isleapyear_arr
@@ -51,6 +52,7 @@ def _period_array_cmp(cls, op):
5152
def wrapper(self, other):
5253
op = getattr(self.asi8, opname)
5354

55+
other = lib.item_from_zerodim(other)
5456
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
5557
return NotImplemented
5658

pandas/core/arrays/timedeltas.py

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def _td_array_cmp(cls, op):
6262
nat_result = opname == '__ne__'
6363

6464
def wrapper(self, other):
65+
other = lib.item_from_zerodim(other)
6566
if isinstance(other, (ABCDataFrame, ABCSeries, ABCIndexClass)):
6667
return NotImplemented
6768

pandas/tests/arithmetic/test_datetime64.py

+12
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def assert_all(obj):
3737
# ------------------------------------------------------------------
3838
# Comparisons
3939

40+
4041
class TestDatetime64DataFrameComparison:
4142
@pytest.mark.parametrize('timestamps', [
4243
[pd.Timestamp('2012-01-01 13:00:00+00:00')] * 2,
@@ -338,6 +339,17 @@ def test_comparison_tzawareness_compat(self, op):
338339

339340
class TestDatetimeIndexComparisons:
340341

342+
# TODO: parametrize over box
343+
def test_compare_zerodim(self, tz_naive_fixture):
344+
# Test comparison with zero-dimensional array is unboxed
345+
tz = tz_naive_fixture
346+
dti = date_range('20130101', periods=3, tz=tz)
347+
348+
other = np.array(dti.to_numpy()[0])
349+
result = dti <= other
350+
expected = np.array([True, False, False])
351+
tm.assert_numpy_array_equal(result, expected)
352+
341353
# TODO: moved from tests.indexes.test_base; parametrize and de-duplicate
342354
@pytest.mark.parametrize("op", [
343355
operator.eq, operator.ne, operator.gt, operator.lt,

pandas/tests/arithmetic/test_period.py

+10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@
2222

2323
class TestPeriodIndexComparisons:
2424

25+
# TODO: parameterize over boxes
26+
def test_compare_zerodim(self):
27+
# GH#26689 make sure we unbox zero-dimensional arrays
28+
pi = pd.period_range('2000', periods=4)
29+
other = np.array(pi.to_numpy()[0])
30+
31+
result = pi <= other
32+
expected = np.array([True, False, False, False])
33+
tm.assert_numpy_array_equal(result, expected)
34+
2535
@pytest.mark.parametrize("other", ["2017", 2017])
2636
def test_eq(self, other):
2737
idx = PeriodIndex(['2017', '2017', '2018'], freq="D")

pandas/tests/arithmetic/test_timedelta64.py

+13
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ def get_upcast_box(box, vector):
3333
class TestTimedelta64ArrayComparisons:
3434
# TODO: All of these need to be parametrized over box
3535

36+
def test_compare_timedelta64_zerodim(self):
37+
# GH#26689 should unbox when comparing with zerodim array
38+
tdi = pd.timedelta_range('2H', periods=4)
39+
other = np.array(tdi.to_numpy()[0])
40+
41+
res = tdi <= other
42+
expected = np.array([True, False, False, False])
43+
tm.assert_numpy_array_equal(res, expected)
44+
45+
with pytest.raises(TypeError):
46+
# zero-dim of wrong dtype should still raise
47+
tdi >= np.array(4)
48+
3649
def test_compare_timedelta_series(self):
3750
# regresssion test for GH#5963
3851
s = pd.Series([timedelta(days=1), timedelta(days=2)])

0 commit comments

Comments
 (0)