Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 8 additions & 12 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import numpy as np
from pandas._libs import (lib, index as libindex, tslib as libts,
algos as libalgos, join as libjoin,
Timestamp, Timedelta, )
Timestamp)
from pandas._libs.lib import is_datetime_array

from pandas.compat import range, u, set_function_name
Expand Down Expand Up @@ -3979,7 +3979,7 @@ def _validate_for_numeric_binop(self, other, op, opstr):
internal method called by ops
"""
# if we are an inheritor of numeric,
# but not actually numeric (e.g. DatetimeIndex/PeriodInde)
# but not actually numeric (e.g. DatetimeIndex/PeriodIndex)
if not self._is_numeric_dtype:
raise TypeError("cannot evaluate a numeric op {opstr} "
"for type: {typ}".format(
Expand All @@ -4006,7 +4006,7 @@ def _validate_for_numeric_binop(self, other, op, opstr):
raise TypeError("cannot evaluate a numeric op "
"with a non-numeric dtype")
elif isinstance(other, (ABCDateOffset, np.timedelta64,
Timedelta, datetime.timedelta)):
datetime.timedelta)):
# higher up to handle
pass
elif isinstance(other, (Timestamp, np.datetime64)):
Expand All @@ -4031,13 +4031,13 @@ def _evaluate_numeric_binop(self, other):

# handle time-based others
if isinstance(other, (ABCDateOffset, np.timedelta64,
Timedelta, datetime.timedelta)):
datetime.timedelta)):
return self._evaluate_with_timedelta_like(other, op, opstr,
reversed)
elif isinstance(other, (Timestamp, np.datetime64)):
return self._evaluate_with_datetime_like(other, op, opstr)

# if we are a reversed non-communative op
# if we are a reversed non-commutative op
values = self.values
if reversed:
values, other = other, values
Expand Down Expand Up @@ -4081,11 +4081,8 @@ def _evaluate_numeric_binop(self, other):
cls.__divmod__ = _make_evaluate_binop(
divmod,
'__divmod__',
constructor=lambda result, **attrs: (
Index(result[0], **attrs),
Index(result[1], **attrs),
),
)
constructor=lambda result, **attrs: (Index(result[0], **attrs),
Index(result[1], **attrs)))

@classmethod
def _add_numeric_methods_unary(cls):
Expand Down Expand Up @@ -4275,8 +4272,7 @@ def _ensure_index(index_like, copy=False):
def _get_na_value(dtype):
if is_datetime64_any_dtype(dtype) or is_timedelta64_dtype(dtype):
return libts.NaT
return {np.datetime64: libts.NaT,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you would make a note, we already have routines for this entire bizness of _get_na_value

pandas.core.dtypes.missing.infer_dtype_for_scalar, so these should be replaced

np.timedelta64: libts.NaT}.get(dtype, np.nan)
return np.nan


def _ensure_has_len(seq):
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/indexes/range.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ def _evaluate_numeric_binop(self, other):
self, other = other, self

try:
# alppy if we have an override
# apply if we have an override
if step:
with np.errstate(all='ignore'):
rstep = step(self._step, other)
Expand Down
43 changes: 8 additions & 35 deletions pandas/core/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,22 +150,7 @@ def names(x):
return new_methods


def add_methods(cls, new_methods, force, select, exclude):
if select and exclude:
raise TypeError("May only pass either select or exclude")

if select:
select = set(select)
methods = {}
for key, method in new_methods.items():
if key in select:
methods[key] = method
new_methods = methods

if exclude:
for k in exclude:
new_methods.pop(k, None)

def add_methods(cls, new_methods, force):
for name, method in new_methods.items():
if force or name not in cls.__dict__:
bind_method(cls, name, method)
Expand All @@ -175,8 +160,8 @@ def add_methods(cls, new_methods, force, select, exclude):
# Arithmetic
def add_special_arithmetic_methods(cls, arith_method=None,
comp_method=None, bool_method=None,
use_numexpr=True, force=False, select=None,
exclude=None, have_divmod=False):
use_numexpr=True, force=False,
have_divmod=False):
"""
Adds the full suite of special arithmetic methods (``__add__``,
``__sub__``, etc.) to the class.
Expand All @@ -195,10 +180,6 @@ def add_special_arithmetic_methods(cls, arith_method=None,
force : bool, default False
if False, checks whether function is defined **on ``cls.__dict__``**
before defining if True, always defines functions on class base
select : iterable of strings (optional)
if passed, only sets functions with names in select
exclude : iterable of strings (optional)
if passed, will not set functions with names in exclude
have_divmod : bool, (optional)
should a divmod method be added? this method is special because it
returns a tuple of cls instead of a single element of type cls
Expand Down Expand Up @@ -247,14 +228,12 @@ def f(self, other):
__ior__=_wrap_inplace_method(new_methods["__or__"]),
__ixor__=_wrap_inplace_method(new_methods["__xor__"])))

add_methods(cls, new_methods=new_methods, force=force, select=select,
exclude=exclude)
add_methods(cls, new_methods=new_methods, force=force)


def add_flex_arithmetic_methods(cls, flex_arith_method,
flex_comp_method=None, flex_bool_method=None,
use_numexpr=True, force=False, select=None,
exclude=None):
use_numexpr=True, force=False):
"""
Adds the full suite of flex arithmetic methods (``pow``, ``mul``, ``add``)
to the class.
Expand All @@ -271,10 +250,6 @@ def add_flex_arithmetic_methods(cls, flex_arith_method,
force : bool, default False
if False, checks whether function is defined **on ``cls.__dict__``**
before defining if True, always defines functions on class base
select : iterable of strings (optional)
if passed, only sets functions with names in select
exclude : iterable of strings (optional)
if passed, will not set functions with names in exclude
"""
# in frame, default axis is 'columns', doesn't matter for series and panel
new_methods = _create_methods(flex_arith_method,
Expand All @@ -289,8 +264,7 @@ def add_flex_arithmetic_methods(cls, flex_arith_method,
if k in new_methods:
new_methods.pop(k)

add_methods(cls, new_methods=new_methods, force=force, select=select,
exclude=exclude)
add_methods(cls, new_methods=new_methods, force=force)


def _align_method_SERIES(left, right, align_asobject=False):
Expand Down Expand Up @@ -389,16 +363,16 @@ def wrapper(left, right, name=name, na_op=na_op):
return NotImplemented

left, right = _align_method_SERIES(left, right)
res_name = _get_series_op_result_name(left, right)

if is_datetime64_dtype(left) or is_datetime64tz_dtype(left):
result = dispatch_to_index_op(op, left, right, pd.DatetimeIndex)
res_name = _get_series_op_result_name(left, right)
return construct_result(left, result,
index=left.index, name=res_name,
dtype=result.dtype)

elif is_timedelta64_dtype(left):
result = dispatch_to_index_op(op, left, right, pd.TimedeltaIndex)
res_name = _get_series_op_result_name(left, right)
return construct_result(left, result,
index=left.index, name=res_name,
dtype=result.dtype)
Expand All @@ -409,7 +383,6 @@ def wrapper(left, right, name=name, na_op=na_op):
rvalues = getattr(rvalues, 'values', rvalues)

result = safe_na_op(lvalues, rvalues)
res_name = _get_series_op_result_name(left, right)
return construct_result(left, result,
index=left.index, name=res_name, dtype=None)

Expand Down