Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: Assorted DTA/TDA/PI bugfixes #24397

Merged
merged 11 commits into from
Dec 25, 2018
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 @@ -1319,6 +1319,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
jreback marked this conversation as resolved.
Show resolved Hide resolved
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