Skip to content

Commit

Permalink
API/DEPR: Remove +/- as setops for DatetimeIndex/PeriodIndex (GH9630) (
Browse files Browse the repository at this point in the history
…#14164)

API/DEPR: Remove +/- as setops for DatetimeIndex/PeriodIndex (GH9630)

xref #13777, deprecations put in place in #9630
  • Loading branch information
jorisvandenbossche committed Sep 7, 2016
1 parent 844d5fb commit e88ad28
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 95 deletions.
25 changes: 22 additions & 3 deletions doc/source/whatsnew/v0.19.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -932,14 +932,16 @@ New Behavior:
Index ``+`` / ``-`` no longer used for set operations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Addition and subtraction of the base Index type (not the numeric subclasses)
Addition and subtraction of the base Index type and of DatetimeIndex
(not the numeric index types)
previously performed set operations (set union and difference). This
behaviour was already deprecated since 0.15.0 (in favor using the specific
``.union()`` and ``.difference()`` methods), and is now disabled. When
possible, ``+`` and ``-`` are now used for element-wise operations, for
example for concatenating strings (:issue:`8227`, :issue:`14127`).
example for concatenating strings or subtracting datetimes
(:issue:`8227`, :issue:`14127`).

Previous Behavior:
Previous behavior:

.. code-block:: ipython

Expand All @@ -962,6 +964,23 @@ For example, the behaviour of adding two integer Indexes:

is unchanged. The base ``Index`` is now made consistent with this behaviour.

Further, because of this change, it is now possible to subtract two
DatetimeIndex objects resulting in a TimedeltaIndex:

Previous behavior:

.. code-block:: ipython

In [1]: pd.DatetimeIndex(['2016-01-01', '2016-01-02']) - pd.DatetimeIndex(['2016-01-02', '2016-01-03'])
FutureWarning: using '-' to provide set differences with datetimelike Indexes is deprecated, use .difference()
Out[1]: DatetimeIndex(['2016-01-01'], dtype='datetime64[ns]', freq=None)

New behavior:

.. ipython:: python

pd.DatetimeIndex(['2016-01-01', '2016-01-02']) - pd.DatetimeIndex(['2016-01-02', '2016-01-03'])


.. _whatsnew_0190.api.difference:

Expand Down
20 changes: 10 additions & 10 deletions pandas/tseries/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
Base and utility classes for tseries type pandas objects.
"""

import warnings
from datetime import datetime, timedelta

from pandas import compat
Expand Down Expand Up @@ -628,10 +627,9 @@ def __add__(self, other):
raise TypeError("cannot add TimedeltaIndex and {typ}"
.format(typ=type(other)))
elif isinstance(other, Index):
warnings.warn("using '+' to provide set union with "
"datetimelike Indexes is deprecated, "
"use .union()", FutureWarning, stacklevel=2)
return self.union(other)
raise TypeError("cannot add {typ1} and {typ2}"
.format(typ1=type(self).__name__,
typ2=type(other).__name__))
elif isinstance(other, (DateOffset, timedelta, np.timedelta64,
tslib.Timedelta)):
return self._add_delta(other)
Expand All @@ -646,20 +644,22 @@ def __add__(self, other):

def __sub__(self, other):
from pandas.core.index import Index
from pandas.tseries.index import DatetimeIndex
from pandas.tseries.tdi import TimedeltaIndex
from pandas.tseries.offsets import DateOffset
if isinstance(other, TimedeltaIndex):
return self._add_delta(-other)
elif isinstance(self, TimedeltaIndex) and isinstance(other, Index):
if not isinstance(other, TimedeltaIndex):
raise TypeError("cannot subtract TimedeltaIndex and {typ}"
.format(typ=type(other)))
.format(typ=type(other).__name__))
return self._add_delta(-other)
elif isinstance(other, DatetimeIndex):
return self._sub_datelike(other)
elif isinstance(other, Index):
warnings.warn("using '-' to provide set differences with "
"datetimelike Indexes is deprecated, "
"use .difference()", FutureWarning, stacklevel=2)
return self.difference(other)
raise TypeError("cannot subtract {typ1} and {typ2}"
.format(typ1=type(self).__name__,
typ2=type(other).__name__))
elif isinstance(other, (DateOffset, timedelta, np.timedelta64,
tslib.Timedelta)):
return self._add_delta(-other)
Expand Down
44 changes: 34 additions & 10 deletions pandas/tseries/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,19 +731,43 @@ def _add_datelike(self, other):
def _sub_datelike(self, other):
# subtract a datetime from myself, yielding a TimedeltaIndex
from pandas import TimedeltaIndex
other = Timestamp(other)
if other is tslib.NaT:
result = self._nat_new(box=False)
# require tz compat
elif not self._has_same_tz(other):
raise TypeError("Timestamp subtraction must have the same "
"timezones or no timezones")
if isinstance(other, DatetimeIndex):
# require tz compat
if not self._has_same_tz(other):
raise TypeError("DatetimeIndex subtraction must have the same "
"timezones or no timezones")
result = self._sub_datelike_dti(other)
elif isinstance(other, (tslib.Timestamp, datetime)):
other = Timestamp(other)
if other is tslib.NaT:
result = self._nat_new(box=False)
# require tz compat
elif not self._has_same_tz(other):
raise TypeError("Timestamp subtraction must have the same "
"timezones or no timezones")
else:
i8 = self.asi8
result = i8 - other.value
result = self._maybe_mask_results(result,
fill_value=tslib.iNaT)
else:
i8 = self.asi8
result = i8 - other.value
result = self._maybe_mask_results(result, fill_value=tslib.iNaT)
raise TypeError("cannot subtract DatetimeIndex and {typ}"
.format(typ=type(other).__name__))
return TimedeltaIndex(result, name=self.name, copy=False)

def _sub_datelike_dti(self, other):
"""subtraction of two DatetimeIndexes"""
if not len(self) == len(other):
raise ValueError("cannot add indices of unequal length")

self_i8 = self.asi8
other_i8 = other.asi8
new_values = self_i8 - other_i8
if self.hasnans or other.hasnans:
mask = (self._isnan) | (other._isnan)
new_values[mask] = tslib.iNaT
return new_values.view('i8')

def _maybe_update_attributes(self, attrs):
""" Update Index attributes (e.g. freq) depending on op """
freq = attrs.get('freq', None)
Expand Down

0 comments on commit e88ad28

Please sign in to comment.