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

BUG: fix Series[timedelta64] arithmetic with Timedelta scalars #18831

Merged
merged 17 commits into from
Dec 31, 2017

Conversation

jbrockmendel
Copy link
Member

@jbrockmendel jbrockmendel commented Dec 19, 2017

closes #18846

Before:

>>> ser = pd.Series([pd.Timedelta(minutes=5, seconds=3)] * 3)
>>> ser.iloc[-1] = np.nan
>>> scalar = pd.Timedelta(minutes=5, seconds=4)
>>> ser // scalar
[...]
TypeError: can only operate on a timedeltas for addition, subtraction, and division, but the operator [__floordiv__] was passed

>>> scalar / ser
0   00:00:00.000000
1   00:00:00.000000
2               NaT
dtype: timedelta64[ns]

>>> scalar.to_pytimedelta() / ser
0   00:00:00.000000
1   00:00:00.000000
2               NaT
dtype: timedelta64[ns]

>>> scalar.to_timedelta64() / ser
0   00:00:00.000000
1   00:00:00.000000
2               NaT
dtype: timedelta64[ns]

>>> scalar.to_pytimedelta() // ser
[...]
TypeError: can only operate on a timedeltas for addition, subtraction, and division, but the operator [__rfloordiv__] was passed

>>> scalar.to_timedelta64() // ser
[...]
TypeError: can only operate on a timedeltas for addition, subtraction, and division, but the operator [__rfloordiv__] was passed

After

>>> ser // scalar
0    0.0
1    0.0
2    NaN
dtype: float64

>>> scalar / ser
0    1.0033
1    1.0033
2       NaN
dtype: float64

>>> scalar.to_pytimedelta() / ser
0    1.0033
1    1.0033
2       NaN
dtype: float64

>>> scalar.to_timedelta64() / ser
0    1.0033
1    1.0033
2       NaN
dtype: float64

>>> scalar.to_pytimedelta() // ser
0    1.0
1    1.0
2    NaN
dtype: float64

>>> scalar.to_timedelta64() // ser
0    1.0
1    1.0
2    NaN
dtype: float64

Also identified a bug in Timedelta.__floordiv__, noted it in #18824, will address that separately.

  • closes #xxxx
  • tests added / passed
  • passes git diff upstream/master -u -- "*.py" | flake8 --diff
  • whatsnew entry

@jbrockmendel jbrockmendel changed the title Timedelta scalars BUG: fix Series[timedelta64] arithmetic with Timedelta scalars Dec 19, 2017
@jbrockmendel
Copy link
Member Author

Travis timeout

@codecov
Copy link

codecov bot commented Dec 19, 2017

Codecov Report

Merging #18831 into master will decrease coverage by <.01%.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #18831      +/-   ##
==========================================
- Coverage   91.58%   91.58%   -0.01%     
==========================================
  Files         150      150              
  Lines       48972    48972              
==========================================
- Hits        44851    44849       -2     
- Misses       4121     4123       +2
Flag Coverage Δ
#multiple 89.94% <ø> (-0.01%) ⬇️
#single 41.72% <ø> (ø) ⬆️
Impacted Files Coverage Δ
pandas/core/ops.py 90.24% <ø> (ø) ⬆️
pandas/util/testing.py 84.74% <0%> (-0.22%) ⬇️

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 21f2412...729d240. Read the comment docs.

@gfyoung gfyoung added Timedelta Timedelta data type Datetime Datetime data dtype labels Dec 19, 2017
Series([0, 0, np.nan]))
# TODO: the Timedelta // td1 fails because of a bug
# in Timedelta.__floordiv__, see GH#18824
# tm.assert_series_equal(tdscalar // td1, Series([1, 1, np.nan]))
Copy link
Member

Choose a reason for hiding this comment

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

I would consider breaking out into a separate test so we can xfail it separately.

Copy link
Member Author

Choose a reason for hiding this comment

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

Works for me. I've got a fix ready pending feedback on #18846.

Copy link
Contributor

Choose a reason for hiding this comment

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

yes would clean up these tests here (IIRC you broke these out by operator elsewhere)

@gfyoung gfyoung added the Bug label Dec 19, 2017
@@ -354,3 +354,4 @@ Other

- Improved error message when attempting to use a Python keyword as an identifier in a ``numexpr`` backed query (:issue:`18221`)
- Bug in :class:`Timestamp` where comparison with an array of ``Timestamp`` objects would result in a ``RecursionError`` (:issue:`15183`)
- Bug in :func:`Series.__floordiv__` and :func:`Series.__rfloordiv__` where operating on a scalar ``timedelta`` raises an exception (:issue:`18824`)
Copy link
Contributor

Choose a reason for hiding this comment

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

don't put things in Other. This is conversion. Also note that a floordiv of scalar / Series was incorrect before.

Copy link
Contributor

Choose a reason for hiding this comment

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

verify that we have a doc example in timedelta.rst as well.

Copy link
Member Author

Choose a reason for hiding this comment

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

Also note that a floordiv of scalar / Series was incorrect before.

Something other than the mention of Series.__rfloordiv__?

Series([0, 0, np.nan]))
# TODO: the Timedelta // td1 fails because of a bug
# in Timedelta.__floordiv__, see GH#18824
# tm.assert_series_equal(tdscalar // td1, Series([1, 1, np.nan]))
Copy link
Contributor

Choose a reason for hiding this comment

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

yes would clean up these tests here (IIRC you broke these out by operator elsewhere)

tdscalar - td1
td1 / tdscalar
tdscalar / td1
tm.assert_series_equal(td1 // tdscalar, Series([0, 0, np.nan]))
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 parametrize these last ones they seem pretty similar

Copy link
Member Author

Choose a reason for hiding this comment

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

This is part of a 127 line test that is all over the place. I'd prefer to clean it up in a follow-up.

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 needs parameterization / refactor, but can follow up.

@@ -962,6 +962,14 @@ def test_timedelta64_ops_nat(self):


class TestDatetimeSeriesArithmetic(object):
@pytest.mark.xfail(reason='GH#18824 bug in Timedelta.__floordiv__')
Copy link
Contributor

Choose a reason for hiding this comment

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

is this the right issue?

Copy link
Member Author

Choose a reason for hiding this comment

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

AFAIK there is no dedicated issue. I made a checkbox for this in 18224.

Copy link
Contributor

Choose a reason for hiding this comment

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

don't mark 18224, its way to big to figure out what you are talking about (you can certainly reference this PR which is I think what you are doing). rather list the PR number (if there isn't an issue). do this generally.

@jbrockmendel
Copy link
Member Author

I think this, #18877, #18875, #18832, and #18783 have all made it through the gauntlet. #18884 and #18762 need clarification on the requested reivisions. Everything else needs attention and will hopefully get it over the weekend.

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.

lgtm. some doc changes. ping on green.

@@ -962,6 +962,14 @@ def test_timedelta64_ops_nat(self):


class TestDatetimeSeriesArithmetic(object):
@pytest.mark.xfail(reason='GH#18824 bug in Timedelta.__floordiv__')
Copy link
Contributor

Choose a reason for hiding this comment

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

don't mark 18224, its way to big to figure out what you are talking about (you can certainly reference this PR which is I think what you are doing). rather list the PR number (if there isn't an issue). do this generally.

@@ -282,6 +282,7 @@ Conversion
- Bug in :meth:`Index.astype` with a categorical dtype where the resultant index is not converted to a :class:`CategoricalIndex` for all types of index (:issue:`18630`)
- Bug in :meth:`Series.astype` and ``Categorical.astype()`` where an existing categorical data does not get updated (:issue:`10696`, :issue:`18593`)
- Bug in :class:`Series` constructor with an int or float list where specifying ``dtype=str``, ``dtype='str'`` or ``dtype='U'`` failed to convert the data elements to strings (:issue:`16605`)
- Bug in :func:`Series.__floordiv__` and :func:`Series.__rfloordiv__` where operating on a scalar ``timedelta`` raises an exception (:issue:`18824`)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would just say floor division here.

tdscalar - td1
td1 / tdscalar
tdscalar / td1
tm.assert_series_equal(td1 // tdscalar, Series([0, 0, np.nan]))
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 needs parameterization / refactor, but can follow up.

@jreback jreback added this to the 0.23.0 milestone Dec 23, 2017
@jbrockmendel
Copy link
Member Author

Ping

@jbrockmendel
Copy link
Member Author

Looks like a test got lost in the last merge, will need to track that down. If there's a way to cancel the CI run, go for it.

@jbrockmendel
Copy link
Member Author

Merge/rebase issue has been resolved. This should be good to go (along with #18849 and #18883).

@pytest.mark.parametrize('scalar_td', [
timedelta(minutes=5, seconds=4),
pytest.param(Timedelta('5m4s'),
marks=pytest.mark.xfail(reason="Timedelta.__floordiv__ "
Copy link
Contributor

Choose a reason for hiding this comment

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

floordiv -> rfloordiv

Copy link
Member Author

Choose a reason for hiding this comment

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

? Both Timedelta.__floordiv__ and Timedelta.__rfloordiv__ are wonky. Or are you referring to something else?

Copy link
Contributor

Choose a reason for hiding this comment

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

you reason is wrong, it should be rfloordiv

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean the reason="Timedelta.__floordiv__...? The test fails because Timedelta.__floordiv__ gets called, not Timedelta.__rfloordiv__.

expected = Series([0, 0, np.nan])
tm.assert_series_equal(result, expected)

# We can test __rfloordiv__ using this syntax,
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this be in the other test? (as the other one is rfloordiv), but this seems to work?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's kind of a man without a country regardless. I didn't want to put it in the rfloordiv test because that was xfailed so putting it there would be akin to not running it at all. But you're right it doesn't really belong in the floordiv test either. I'm open to suggestions.

Copy link
Contributor

Choose a reason for hiding this comment

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

then make another test for it

@jreback
Copy link
Contributor

jreback commented Dec 31, 2017

thanks!

@jbrockmendel jbrockmendel deleted the timedelta_scalars branch February 11, 2018 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Datetime Datetime data dtype Timedelta Timedelta data type
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: Timedelta.__floordiv__ - need historical context
3 participants