-
-
Notifications
You must be signed in to change notification settings - Fork 18.3k
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
DEPR: deprecate integer add/sub with DTI/TDI/PI/Timestamp/Period #22535
Changes from 36 commits
145eb6a
d5c5f28
3fb29bc
81c9eab
26c9966
11959b1
8952cb5
7c79364
d0fa41a
c23346b
f6daf34
b7e3dcf
2a829d3
f24643c
6fea2a8
b469bef
20d58fa
984bc7e
841718c
7e7a348
17f6be0
29cca46
b0a222a
14b9eaf
55dc265
9443df9
d46452d
af31b0c
0bebbe0
c7dd7ce
ca55b4a
394a3b8
3884bb4
a15d9e4
5256671
d8865d7
da72660
fcd65b3
6ded8b1
4a7b589
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -955,6 +955,53 @@ Deprecations | |
- :meth:`Timestamp.tz_localize`, :meth:`DatetimeIndex.tz_localize`, and :meth:`Series.tz_localize` have deprecated the ``errors`` argument in favor of the ``nonexistent`` argument (:issue:`8917`) | ||
- The class ``FrozenNDArray`` has been deprecated. When unpickling, ``FrozenNDArray`` will be unpickled to ``np.ndarray`` once this class is removed (:issue:`9031`) | ||
|
||
.. _whatsnew_0240.deprecations.datetimelike_int_ops: | ||
|
||
Integer Addition/Subtraction with Datetime-like Classes Is Deprecated | ||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
In the past, users could add or subtract integers or integer-dtypes arrays | ||
from :class:`Period`, :class:`PeriodIndex`, and in some cases | ||
:class:`Timestamp`, :class:`DatetimeIndex` and :class:`TimedeltaIndex`. | ||
|
||
This usage is now deprecated. Instead add or subtract integer multiples of | ||
the object's ``freq`` attribute (:issue:`21939`) | ||
|
||
Previous Behavior: | ||
|
||
.. code-block:: ipython | ||
|
||
In [3]: per = pd.Period('2016Q1') | ||
In [4]: per + 3 | ||
Out[4]: Period('2016Q4', 'Q-DEC') | ||
|
||
In [5]: ts = pd.Timestamp('1994-05-06 12:15:16', freq=pd.offsets.Hour()) | ||
In [6]: ts + 2 | ||
Out[6]: Timestamp('1994-05-06 14:15:16', freq='H') | ||
|
||
In [7]: tdi = pd.timedelta_range('1D', periods=2) | ||
In [8]: tdi - np.array([2, 1]) | ||
Out[8]: TimedeltaIndex(['-1 days', '1 days'], dtype='timedelta64[ns]', freq=None) | ||
|
||
In [9]: dti = pd.date_range('2001-01-01', periods=2, freq='7D') | ||
In [10]: dti + pd.Index([1, 2]) | ||
Out[10]: DatetimeIndex(['2001-01-08', '2001-01-22'], dtype='datetime64[ns]', freq=None) | ||
|
||
Current Behavior: | ||
|
||
.. ipython:: python | ||
|
||
per = pd.Period('2016Q1') | ||
per + 3 * per.freq | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you might want to show the deprecation warning itself on 1 case here (you will need to add |
||
ts = pd.Timestamp('1994-05-06 12:15:16', freq=pd.offsets.Hour()) | ||
ts + 2 * ts.freq | ||
|
||
tdi = pd.timedelta_range('1D', periods=2) | ||
tdi - np.array([2 * tdi.freq, 1 * tdi.freq]) | ||
|
||
dti = pd.date_range('2001-01-01', periods=2, freq='7D') | ||
dti + pd.Index([1 * dti.freq, 2 * dti.freq]) | ||
|
||
.. _whatsnew_0240.prior_deprecations: | ||
|
||
Removal of prior version deprecations/changes | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,8 +40,19 @@ from timezones cimport ( | |
_zero_time = datetime_time(0, 0) | ||
_no_input = object() | ||
|
||
|
||
# ---------------------------------------------------------------------- | ||
|
||
def int_op_deprecated(obj): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok this looks good. can you rename to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
# GH#22535 add/sub of integers and int-arrays is deprecated | ||
if obj.freq is not None: | ||
warnings.warn("Addition/subtraction of integers and integer-arrays " | ||
"to {cls} is deprecated, will be removed in a future " | ||
"version. Instead of adding/subtracting `n`, use " | ||
"`n * self.freq`" | ||
.format(cls=type(obj).__name__), | ||
FutureWarning) | ||
|
||
|
||
cdef inline object create_timestamp_from_ts(int64_t value, | ||
npy_datetimestruct dts, | ||
|
@@ -315,14 +326,17 @@ cdef class _Timestamp(datetime): | |
return np.datetime64(self.value, 'ns') | ||
|
||
def __add__(self, other): | ||
cdef int64_t other_int, nanos | ||
cdef: | ||
int64_t other_int, nanos | ||
|
||
if is_timedelta64_object(other): | ||
other_int = other.astype('timedelta64[ns]').view('i8') | ||
return Timestamp(self.value + other_int, | ||
tz=self.tzinfo, freq=self.freq) | ||
|
||
elif is_integer_object(other): | ||
int_op_deprecated(self) | ||
|
||
if self is NaT: | ||
# to be compat with Period | ||
return NaT | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
) | ||
from pandas._libs.tslibs import period as libperiod | ||
from pandas._libs.tslibs.timedeltas import delta_to_nanoseconds, Timedelta | ||
from pandas._libs.tslibs.timestamps import int_op_deprecated | ||
from pandas._libs.tslibs.fields import isleapyear_arr | ||
from pandas.util._decorators import cache_readonly, Appender | ||
from pandas.util._validators import validate_fillna_kwargs | ||
|
@@ -592,7 +593,7 @@ def to_timestamp(self, freq=None, how='start'): | |
return self.to_timestamp(how='start') + adjust | ||
else: | ||
adjust = Timedelta(1, 'ns') | ||
return (self + 1).to_timestamp(how='start') - adjust | ||
return (self + self.freq).to_timestamp(how='start') - adjust | ||
|
||
if freq is None: | ||
base, mult = frequencies.get_freq_code(self.freq) | ||
|
@@ -718,10 +719,15 @@ def _sub_period(self, other): | |
@Appender(dtl.DatetimeLikeArrayMixin._addsub_int_array.__doc__) | ||
def _addsub_int_array( | ||
self, | ||
other, # type: Union[Index, ExtensionArray, np.ndarray[int]] | ||
op, # type: Callable[Any, Any] | ||
other, # type: Union[Index, ExtensionArray, np.ndarray[int]] | ||
op, # type: Callable[Any, Any] | ||
suppress=False # type: bool | ||
): | ||
# type: (...) -> PeriodArray | ||
|
||
if not suppress: | ||
int_op_deprecated(self) | ||
|
||
assert op in [operator.add, operator.sub] | ||
if op is operator.sub: | ||
other = -other | ||
|
@@ -778,7 +784,7 @@ def _add_delta_tdi(self, other): | |
assert isinstance(self.freq, Tick) # checked by calling function | ||
|
||
delta = self._check_timedeltalike_freq_compat(other) | ||
return self._addsub_int_array(delta, operator.add).asi8 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. huh? what are you adding a new kwarg for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We still call But actually now that the warning is a one-liner, it is less cumbersome to put it directly in |
||
return self._addsub_int_array(delta, operator.add, suppress=True).asi8 | ||
|
||
def _add_delta(self, other): | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these should be executable statements, e.g. just show the input, the output is run
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. One day I'll get the hang of this doc system...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you can update these
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need the ipython line numbers