Skip to content

Commit

Permalink
BUG: Assorted DTA/TDA/PI bugfixes (pandas-dev#24397)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and Pingviinituutti committed Feb 28, 2019
1 parent b40f4a2 commit 144f888
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 2 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.24.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,7 @@ Datetimelike
- Bug in :class:`DatetimeIndex` and :class:`TimedeltaIndex` where indexing with ``Ellipsis`` would incorrectly lose the index's ``freq`` attribute (:issue:`21282`)
- Clarified error message produced when passing an incorrect ``freq`` argument to :class:`DatetimeIndex` with ``NaT`` as the first entry in the passed data (:issue:`11587`)
- Bug in :func:`to_datetime` where ``box`` and ``utc`` arguments were ignored when passing a :class:`DataFrame` or ``dict`` of unit mappings (:issue:`23760`)
- Bug in :class:`PeriodIndex` where comparisons against an array-like object with length 1 failed to raise ``ValueError`` (:issue:`23078`)

Timedelta
^^^^^^^^^
Expand Down
3 changes: 2 additions & 1 deletion pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -1298,7 +1298,8 @@ def _ensure_datetimelike_to_i8(other, to_utc=False):

if lib.is_scalar(other) and isna(other):
return iNaT
elif isinstance(other, (PeriodArray, ABCIndexClass)):
elif isinstance(other, (PeriodArray, ABCIndexClass,
DatetimeLikeArrayMixin)):
# convert tz if needed
if getattr(other, 'tz', None) is not None:
if to_utc:
Expand Down
6 changes: 5 additions & 1 deletion pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ def _dt_array_cmp(cls, op):
def wrapper(self, other):
meth = getattr(dtl.DatetimeLikeArrayMixin, opname)

other = lib.item_from_zerodim(other)

if isinstance(other, (datetime, np.datetime64, compat.string_types)):
if isinstance(other, (datetime, np.datetime64)):
# GH#18435 strings get a pass from tzawareness compat
Expand All @@ -111,8 +113,10 @@ def wrapper(self, other):
result = op(self.asi8, other.view('i8'))
if isna(other):
result.fill(nat_result)
elif lib.is_scalar(other):
elif lib.is_scalar(other) or np.ndim(other) == 0:
return ops.invalid_comparison(self, other, op)
elif len(other) != len(self):
raise ValueError("Lengths must match")
else:
if isinstance(other, list):
try:
Expand Down
3 changes: 3 additions & 0 deletions pandas/core/arrays/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ def wrapper(self, other):
# return here with an unboxed PeriodArray). But before we do that,
# we do a bit of validation on type (Period) and freq, so that our
# error messages are sensible
if is_list_like(other) and len(other) != len(self):
raise ValueError("Lengths must match")

not_implemented = isinstance(other, (ABCSeries, ABCIndexClass))
if not_implemented:
other = other._values
Expand Down
3 changes: 3 additions & 0 deletions pandas/core/arrays/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ def wrapper(self, other):
elif not is_list_like(other):
return ops.invalid_comparison(self, other, op)

elif len(other) != len(self):
raise ValueError("Lengths must match")

else:
try:
other = type(self)._from_sequence(other)._data
Expand Down
1 change: 1 addition & 0 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5094,6 +5094,7 @@ def _evaluate_numeric_unary(self):
attrs = self._maybe_update_attributes(attrs)
return Index(op(self.values), **attrs)

_evaluate_numeric_unary.__name__ = opstr
return _evaluate_numeric_unary

cls.__neg__ = _make_evaluate_unary(operator.neg, '__neg__')
Expand Down
3 changes: 3 additions & 0 deletions pandas/core/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -1390,6 +1390,7 @@ def f(self, other):

return self

f.__name__ = "__i{name}__".format(name=method.__name__.strip("__"))
return f

new_methods.update(
Expand Down Expand Up @@ -1574,6 +1575,7 @@ def wrapper(left, right):
return construct_result(left, result,
index=left.index, name=res_name, dtype=None)

wrapper.__name__ = op_name
return wrapper


Expand Down Expand Up @@ -1762,6 +1764,7 @@ def wrapper(self, other, axis=None):
return self._constructor(res_values, index=self.index,
name=res_name, dtype='bool')

wrapper.__name__ = op_name
return wrapper


Expand Down
1 change: 1 addition & 0 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ def wrapper(self):
raise TypeError("cannot convert the series to "
"{0}".format(str(converter)))

wrapper.__name__ = "__{name}__".format(name=converter.__name__)
return wrapper

# ----------------------------------------------------------------------
Expand Down
24 changes: 24 additions & 0 deletions pandas/tests/arrays/test_datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,21 @@ def timedelta_index(request):
class SharedTests(object):
index_cls = None

def test_compare_len1_raises(self):
# make sure we raise when comparing with different lengths, specific
# to the case where one has length-1, which numpy would broadcast
data = np.arange(10, dtype='i8')

idx = self.index_cls._simple_new(data, freq='D')
arr = self.array_cls(idx)

with pytest.raises(ValueError, match="Lengths must match"):
arr == arr[:1]

# test the index classes while we're at it, GH#23078
with pytest.raises(ValueError, match="Lengths must match"):
idx <= idx[[0]]

def test_take(self):
data = np.arange(100, dtype='i8')
np.random.shuffle(data)
Expand Down Expand Up @@ -119,6 +134,15 @@ class TestDatetimeArray(SharedTests):
index_cls = pd.DatetimeIndex
array_cls = DatetimeArray

def test_round(self, tz_naive_fixture):
# GH#24064
tz = tz_naive_fixture
dti = pd.date_range('2016-01-01 01:01:00', periods=3, freq='H', tz=tz)

result = dti.round(freq='2T')
expected = dti - pd.Timedelta(minutes=1)
tm.assert_index_equal(result, expected)

def test_array_object_dtype(self, tz_naive_fixture):
# GH#23524
tz = tz_naive_fixture
Expand Down

0 comments on commit 144f888

Please sign in to comment.