Skip to content
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

Merged
merged 40 commits into from
Nov 1, 2018

Conversation

jbrockmendel
Copy link
Member

@jbrockmendel jbrockmendel commented Aug 29, 2018

Discussed in #21939; these operations cause headaches and internal-inconsistencies (e.g. ATM Timedelta is the only one of the related classes that doesn't support integer ops)

pandas/core/arrays/datetimelike.py Outdated Show resolved Hide resolved
@mroeschke
Copy link
Member

There are some reference to integer arithmetic in timeseries.rst (e.g. https://pandas.pydata.org/pandas-docs/stable/timeseries.html#period). It's probably a good idea to scrub them so we don't advertise depreciated functionality

@jbrockmendel
Copy link
Member Author

Is there a usage of tm.assert_produces_warning to use when we expect the affected code to produce two warnings?

@jreback
Copy link
Contributor

jreback commented Aug 31, 2018

Is there a usage of tm.assert_produces_warning to use when we expect the affected code to produce two warnings?

I think you can pass a list? (you can to the underlying machinery, so maybe this just works, if not it should)

@jreback jreback added the Deprecate Functionality to remove in pandas label Aug 31, 2018
@jreback
Copy link
Contributor

jreback commented Aug 31, 2018

@jbrockmendel pls add to the list in the deprecation issue (#6581) , when we merge can check the box

@@ -514,6 +514,8 @@ Deprecations
- The signature of :meth:`Series.to_csv` has been uniformed to that of doc:meth:`DataFrame.to_csv`: the name of the first argument is now 'path_or_buf', the order of subsequent arguments has changed, the 'header' argument now defaults to True. (:issue:`19715`)
- :meth:`Categorical.from_codes` has deprecated providing float values for the ``codes`` argument. (:issue:`21767`)
- :func:`pandas.read_table` is deprecated. Instead, use :func:`pandas.read_csv` passing ``sep='\t'`` if necessary (:issue:`21948`)
- Addition or subtraction of integers with :class:`Timestamp`, :class:`Period`, :class:`DatetimeIndex`, :class:`TimedeltaIndex`, :class:`PeriodIndex` is deprecated, will be removed in a future version (:issue:`21939`)
- Addition or subtraction of integer-dtyped arrays with:class:`DatetimeIndex`, :class:`TimedeltaIndex`, :class:`PeriodIndex` is deprecated, will be removed in a future version (:issue:`21939`)
Copy link
Contributor

Choose a reason for hiding this comment

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

space after with


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 None:
Copy link
Contributor

Choose a reason for hiding this comment

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

is it necessary for freq to be none here? (we don't have this check elsewhere)

Copy link
Member Author

Choose a reason for hiding this comment

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

Should be not-None, good catch.

Copy link
Contributor

Choose a reason for hiding this comment

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

does this need to be changed?

@jreback jreback added Datetime Datetime data dtype Numeric Operations Arithmetic, Comparison, and Logical operations labels Aug 31, 2018
@jbrockmendel
Copy link
Member Author

Will update as indicated. BTW gentle ping re #22350; many upcoming PRs touch those files, so it'd be helpful to get it out of the way.

@jbrockmendel
Copy link
Member Author

I think you can pass a list? (you can to the underlying machinery, so maybe this just works, if not it should)

Doesn't look like it, I'll fix that.

@jbrockmendel
Copy link
Member Author

I think you can pass a list? (you can to the underlying machinery, so maybe this just works, if not it should)

Trying to implement this, I've got most of it working, but can find no combination of stacklevel= parameters that don't cause the "not set with correct stacklevel" assertion to fail. Who is the team expert on this?

@jreback
Copy link
Contributor

jreback commented Sep 4, 2018

don't worry about checking the stacklevel too much, the idea is to raise it to a reasonable level, e.g. if you run the tests, it should point to the top-level of the code where its most releveant (rather than a lower level call). Just pick something that looks reasonable, and you can turn off the stacklevel check itself.

@pep8speaks
Copy link

pep8speaks commented Sep 5, 2018

Hello @jbrockmendel! Thanks for updating the PR.

Comment last updated on October 15, 2018 at 19:17 Hours UTC

@codecov
Copy link

codecov bot commented Sep 5, 2018

Codecov Report

Merging #22535 into master will decrease coverage by <.01%.
The diff coverage is 81.25%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #22535      +/-   ##
==========================================
- Coverage   92.21%   92.21%   -0.01%     
==========================================
  Files         161      161              
  Lines       51173    51191      +18     
==========================================
+ Hits        47190    47206      +16     
- Misses       3983     3985       +2
Flag Coverage Δ
#multiple 90.65% <81.25%> (-0.01%) ⬇️
#single 42.22% <3.12%> (-0.02%) ⬇️
Impacted Files Coverage Δ
pandas/core/arrays/datetimelike.py 96.16% <100%> (+0.04%) ⬆️
pandas/core/arrays/period.py 97.48% <100%> (ø) ⬆️
pandas/plotting/_converter.py 63.67% <50%> (ø) ⬆️
pandas/core/resample.py 96.99% <75%> (ø) ⬆️
pandas/tseries/offsets.py 97.22% <83.33%> (-0.15%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update de39bfc...4a7b589. Read the comment docs.

@jreback jreback added this to the 0.24.0 milestone Sep 8, 2018

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 None:
Copy link
Contributor

Choose a reason for hiding this comment

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

does this need to be changed?

@@ -556,6 +556,8 @@ Deprecations
- :func:`pandas.read_table` is deprecated. Instead, use :func:`pandas.read_csv` passing ``sep='\t'`` if necessary (:issue:`21948`)
- :meth:`Series.str.cat` has deprecated using arbitrary list-likes *within* list-likes. A list-like container may still contain
many ``Series``, ``Index`` or 1-dimensional ``np.ndarray``, or alternatively, only scalar values. (:issue:`21950`)
- Addition or subtraction of integers with :class:`Timestamp`, :class:`Period`, :class:`DatetimeIndex`, :class:`TimedeltaIndex`, :class:`PeriodIndex` is deprecated, will be removed in a future version (:issue:`21939`)
Copy link
Contributor

Choose a reason for hiding this comment

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

pls make a sub-section and show what is being deprecated and what is the alternative. this is actually a rather large change.

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'll try to get to this tomorrow.

Copy link
Member Author

Choose a reason for hiding this comment

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

@jreback just added this section; wasn't sure on where in the doc to put it and the ipython/code-block syntax is a shot in the dark. Please advise.

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

need to fix the docs and consolidate the warnings to a single function.

Current Behavior:

.. ipython:: python

Copy link
Contributor

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

@@ -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 "
Copy link
Contributor

Choose a reason for hiding this comment

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

can you do this


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:
Copy link
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

small change, otherwise lgtm. ping on green.

# ----------------------------------------------------------------------

def int_op_deprecated(obj):
Copy link
Contributor

Choose a reason for hiding this comment

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

ok this looks good. can you rename to
``maybe_integer_op_deprecated`

Copy link
Member Author

Choose a reason for hiding this comment

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

sure


per = pd.Period('2016Q1')
per + 3 * per.freq

Copy link
Contributor

Choose a reason for hiding this comment

The 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 :okwarning: though)

@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

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

huh? what are you adding a new kwarg for?

Copy link
Member Author

Choose a reason for hiding this comment

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

We still call _addsub_int_array internally from a few places (here and in DateOffset apply_index methods) and want to suppress the warning.

But actually now that the warning is a one-liner, it is less cumbersome to put it directly in __add__/__sub__. Will change.

@@ -1066,14 +1067,16 @@ def test_dti_iadd_int(self, tz_naive_fixture, one):
periods=10, tz=tz)
expected = pd.date_range('2000-01-01 10:00', freq='H',
periods=10, tz=tz)
rng += one
with tm.assert_produces_warning(FutureWarning, check_stacklevel=False):
Copy link
Contributor

Choose a reason for hiding this comment

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

why can't you check the stacklevel anymore?

Copy link
Member Author

Choose a reason for hiding this comment

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

We basically never did. I never got the stacklevel checks to pass in any consistent way.

if self.n > 0:
shifted = (i.to_perioddelta('B') - time).asi8 != 0

# Integer-array addition is deprecated, so we use
Copy link
Contributor

Choose a reason for hiding this comment

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

this comment is out of date, but can change later

@jreback jreback merged commit a4f9a44 into pandas-dev:master Nov 1, 2018
@jreback
Copy link
Contributor

jreback commented Nov 1, 2018

thanks @jbrockmendel sometimes they take a lot of iterations :-D

@jbrockmendel
Copy link
Member Author

It's all about the power of Teamwork.

@jorisvandenbossche
Copy link
Member

jorisvandenbossche commented Dec 16, 2018

@jbrockmendel what was actually the rationale of deprecating it for Periods as well?
The issue that is closed by this (#21939) discusses it for DatetimeIndex/TimedeltaIndex, but I think says to keep it for PeriodIndex for now.

In any case, for PeriodIndex, this was an explicitly documented behaviour, and the documentation is now no longer up to date.
But instead of updating the docs, I think we should also reconsider the deprecation. Or at least provide a clear alternative way.

(and to be clear: I fully agree with the deprecation for DatetimeIndex / TimedeltaIndex!)

@jbrockmendel
Copy link
Member Author

I think we should also reconsider the deprecation

I'm open to that. The ones I care about are the TS/TD/DTI/TDI

@jorisvandenbossche
Copy link
Member

After commenting here I opened an issue with the same content: #24305. Can you post it there?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Datetime Datetime data dtype Deprecate Functionality to remove in pandas Numeric Operations Arithmetic, Comparison, and Logical operations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DISC] DatetimeIndex/TimedeltaIndex ops with integers should deprecated
5 participants