8000 Implement mul, floordiv, mod, divmod, and reversed directly in TimedeltaArray by jbrockmendel · Pull Request #23885 · pandas-dev/pandas · GitHub
[go: up one dir, main page]

Skip to content

Implement mul, floordiv, mod, divmod, and reversed directly in TimedeltaArray #23885

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

Merged
merged 16 commits into from
Dec 3, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
Prev Previous commit
Next Next commit
remove no-longer-necessary
  • Loading branch information
jbrockmendel committed Nov 29, 2018
commit ef257504bc7d034145501fff2aa30661a684479c
50 changes: 0 additions & 50 deletions pandas/core/arrays/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,29 +105,6 @@ def wrapper(self, other):
return compat.set_function_name(wrapper, opname, cls)


def _wrap_tdi_op(op):
"""
Instead of re-implementing multiplication/division etc operations
in the Array class, for now we dispatch to the TimedeltaIndex
implementations.
"""
# TODO: implement directly here and wrap in TimedeltaIndex, instead of
# the other way around
def method(self, other):
if isinstance(other, (ABCSeries, ABCDataFrame, ABCIndexClass)):
return NotImplemented

from pandas import TimedeltaIndex
obj = TimedeltaIndex(self)
result = op(obj, other)
if is_timedelta64_dtype(result):
return type(self)(result)
return np.array(result)

method.__name__ = '__{name}__'.format(name=op.__name__)
return method


class TimedeltaArrayMixin(dtl.DatetimeLikeArrayMixin):
_typ = "timedeltaarray"
__array_priority__ = 1000
Expand Down Expand Up @@ -325,33 +302,6 @@ def _addsub_offset_array(self, other, op):
raise TypeError("Cannot add/subtract non-tick DateOffset to {cls}"
.format(cls=type(self).__name__))

def _evaluate_with_timedelta_like(self, other, op):
if isinstance(other, ABCSeries):
# GH#19042
return NotImplemented

opstr = '__{opname}__'.format(opname=op.__name__).replace('__r', '__')
# allow division by a timedelta
if opstr in ['__div__', '__truediv__', '__floordiv__']:
if _is_convertible_to_td(other):
other = Timedelta(other)
if isna(other):
raise NotImplementedError(
"division by pd.NaT not implemented")

i8 = self.asi8
left, right = i8, other.value

if opstr in ['__floordiv__']:
result = op(left, right)
else:
result = op(left, np.float64(right))
result = self._maybe_mask_results(result, fill_value=None,
convert='float64')
return result

return NotImplemented

def __mul__(self, other):
other = lib.item_from_zerodim(other)
Copy link
Contributor

Choose a reason for hiding this comment

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

so you don't do this everywhere?

maybe add a function that you call to avoid repeating code

def _prepare_other(other):
   other = lib.item_from_zerodim(other)
   if is_list_like(other) and not hasattr(other, "dtype"):
            # list, tuple
            other = np.array(other)
   return other

Copy link
Member Author

Choose a reason for hiding this comment

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

I opened #23853 for exactly this reason. It merits a dedicated PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

right, but now you are missing some code here on several of the operators (from_zero_dim), so maybe better to fix now.


Expand Down
28 changes: 13 additions & 15 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5017,21 +5017,19 @@ def _add_numeric_methods_binary(cls):
cls.__rpow__ = _make_arithmetic_op(ops.rpow, cls)
cls.__pow__ = _make_arithmetic_op(operator.pow, cls)

if not issubclass(cls, ABCTimedeltaIndex):
# GH#23829 TimedeltaIndex defines these directly
cls.__truediv__ = _make_arithmetic_op(operator.truediv, cls)
cls.__rtruediv__ = _make_arithmetic_op(ops.rtruediv, cls)
if not compat.PY3:
cls.__div__ = _make_arithmetic_op(operator.div, cls)
cls.__rdiv__ = _make_arithmetic_op(ops.rdiv, cls)

# TODO: rmod? rdivmod?
cls.__mod__ = _make_arithmetic_op(operator.mod, cls)
cls.__floordiv__ = _make_arithmetic_op(operator.floordiv, cls)
cls.__rfloordiv__ = _make_arithmetic_op(ops.rfloordiv, cls)
cls.__divmod__ = _make_arithmetic_op(divmod, cls)
cls.__mul__ = _make_arithmetic_op(operator.mul, cls)
cls.__rmul__ = _make_arithmetic_op(ops.rmul, cls)
cls.__truediv__ = _make_arithmetic_op(operator.truediv, cls)
cls.__rtruediv__ = _make_arithmetic_op(ops.rtruediv, cls)
if not compat.PY3:
cls.__div__ = _make_arithmetic_op(operator.div, cls)
cls.__rdiv__ = _make_arithmetic_op(ops.rdiv, cls)

# TODO: rmod? rdivmod?
cls.__mod__ = _make_arithmetic_op(operator.mod, cls)
cls.__floordiv__ = _make_arithmetic_op(operator.floordiv, cls)
cls.__rfloordiv__ = _make_arithmetic_op(ops.rfloordiv, cls)
cls.__divmod__ = _make_arithmetic_op(divmod, cls)
cls.__mul__ = _make_arithmetic_op(operator.mul, cls)
cls.__rmul__ = _make_arithmetic_op(ops.rmul, cls)

@classmethod
def _add_numeric_methods_unary(cls):
Expand Down
6 changes: 1 addition & 5 deletions pandas/core/indexes/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,6 @@ def _maybe_update_attributes(self, attrs):
attrs['freq'] = 'infer'
return attrs

def _evaluate_with_timedelta_like(self, other, op):
result = TimedeltaArray._evaluate_with_timedelta_like(self, other, op)
return wrap_arithmetic_op(self, other, result)

# -------------------------------------------------------------------
# Rendering Methods

Expand Down Expand Up @@ -700,7 +696,7 @@ def delete(self, loc):


TimedeltaIndex._add_comparison_ops()
TimedeltaIndex._add_numeric_methods()
TimedeltaIndex._add_numeric_methods_unary()
TimedeltaIndex._add_logical_methods_disabled()
TimedeltaIndex._add_datetimelike_methods()

Expand Down
0