-
-
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 14 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 |
---|---|---|
|
@@ -575,6 +575,57 @@ Deprecations | |
- :meth:`FrozenNDArray.searchsorted` has deprecated the ``v`` parameter in favor of ``value`` (:issue:`14645`) | ||
- :func:`DatetimeIndex.shift` now accepts ``periods`` argument instead of ``n`` for consistency with :func:`Index.shift` and :func:`Series.shift`. Using ``n`` throws a deprecation warning (:issue:`22458`) | ||
|
||
.. _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 | ||
|
||
In [3]: per = pd.Period('2016Q1') | ||
In [4]: per + 3 * per.freq | ||
Out[4]: Period('2016Q4', 'Q-DEC') | ||
|
||
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 |
||
In [5]: ts = pd.Timestamp('1994-05-06 12:15:16', freq=pd.offsets.Hour()) | ||
In [6]: ts + 2 * ts.freq | ||
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 * tdi.freq, 1 * tdi.freq]) | ||
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 * dti.freq, 2 * dti.freq]) | ||
Out[10]: DatetimeIndex(['2001-01-08', '2001-01-22'], dtype='datetime64[ns]', freq=None) | ||
|
||
.. _whatsnew_0240.prior_deprecations: | ||
|
||
Removal of prior version deprecations/changes | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# -*- coding: utf-8 -*- | ||
from datetime import datetime, date | ||
import warnings | ||
|
||
from cpython cimport ( | ||
PyUnicode_Check, | ||
|
@@ -1645,6 +1646,13 @@ cdef class _Period(object): | |
elif other is NaT: | ||
return NaT | ||
elif util.is_integer_object(other): | ||
warnings.warn("Addition of integers to {cls} is " | ||
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. can you call a function for this warning (not sure exatcly where), rather than repeating each time, prob need to pass in the level 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. Not sure what you have in mind. Just a one-liner containing this warning? 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. yeah a module level function just seems better than copy-pasting 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. can you do this |
||
"deprecated, will be removed in a future " | ||
"version. Instead of adding `n`, add " | ||
"`n * self.freq`" | ||
.format(cls=type(self).__name__), | ||
FutureWarning) | ||
|
||
ordinal = self.ordinal + other * self.freq.n | ||
return Period(ordinal=ordinal, freq=self.freq) | ||
elif (PyDateTime_Check(other) or | ||
|
@@ -1671,6 +1679,13 @@ cdef class _Period(object): | |
neg_other = -other | ||
return self + neg_other | ||
elif util.is_integer_object(other): | ||
warnings.warn("Subtraction of integers from {cls} is " | ||
"deprecated, will be removed in a future " | ||
"version. Instead of subtracting `n`, subtract " | ||
"`n * self.freq`" | ||
.format(cls=type(self).__name__), | ||
FutureWarning) | ||
|
||
ordinal = self.ordinal - other * self.freq.n | ||
return Period(ordinal=ordinal, freq=self.freq) | ||
elif is_period_object(other): | ||
|
@@ -1756,7 +1771,7 @@ cdef class _Period(object): | |
def end_time(self): | ||
# freq.n can't be negative or 0 | ||
# ordinal = (self + self.freq.n).start_time.value - 1 | ||
ordinal = (self + 1).start_time.value - 1 | ||
ordinal = (self + self.freq).start_time.value - 1 | ||
return Timestamp(ordinal) | ||
|
||
def to_timestamp(self, freq=None, how='start', tz=None): | ||
|
@@ -1783,7 +1798,8 @@ cdef class _Period(object): | |
|
||
end = how == 'E' | ||
if end: | ||
return (self + 1).to_timestamp(how='start') - Timedelta(1, 'ns') | ||
endpoint = (self + self.freq).to_timestamp(how='start') | ||
return endpoint - Timedelta(1, 'ns') | ||
|
||
if freq is None: | ||
base, mult = get_freq_code(self.freq) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -250,14 +250,23 @@ 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): | ||
if self.freq is not None: | ||
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. so I would put the warning function in this module and just call it from higher levels |
||
warnings.warn("Addition of integers to {cls} is " | ||
"deprecated, will be removed in a future " | ||
"version. Instead of adding `n`, add " | ||
"`n * self.freq`" | ||
.format(cls=type(self).__name__), | ||
FutureWarning) | ||
|
||
if self is NaT: | ||
# to be compat with Period | ||
return NaT | ||
|
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