-
-
Notifications
You must be signed in to change notification settings - Fork 18.1k
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
Fix Index __mul__-like ops with timedelta scalars #19333
Conversation
doc/source/whatsnew/v0.23.0.txt
Outdated
@@ -428,7 +428,9 @@ Conversion | |||
- Bug in localization of a naive, datetime string in a ``Series`` constructor with a ``datetime64[ns, tz]`` dtype (:issue:`174151`) | |||
- :func:`Timestamp.replace` will now handle Daylight Savings transitions gracefully (:issue:`18319`) | |||
- Bug in :class:`Index` multiplication and division methods where operating with a ``Series`` would return an ``Index`` object instead of a ``Series`` object (:issue:`19042`) | |||
|
|||
- Multiplication of :class:`TimedeltaIndex` by ``TimedeltaIndex`` will now raise ``TypeError`` instead of raising ``ValueError`` in cases of length mis-match (:issue:`????`) |
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.
when you don't have an issue number, use the PR number
@@ -3864,7 +3864,21 @@ def dropna(self, how='any'): | |||
return self._shallow_copy() | |||
|
|||
def _evaluate_with_timedelta_like(self, other, op, opstr, reversed=False): | |||
raise TypeError("can only perform ops with timedelta like values") | |||
# Timedelta knows how to operate with np.array, so dispatch to that |
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.
shouldn't this be left alone, and rather define this in TimedeltaIndex
?
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.
This for for numeric-dtyped indexes. e.g. pd.Index(range(3)) * pd.Timedelta(days=1)
goes through this path.
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.
why doesn't this just raise NotImplementedError? which then Timedelta would handle? or is that too recursive a path?
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.
For one thing b/c there’s pytimedelta and timedelta64 that need to be handled.
I just updated the whatsnew, to be more organized, so rebase again. |
OK. Should I put the multiplication/division stuff in Numeric instead of Conversion? A few days back you suggested an Ops section, but I wasn't clear on what the scope of that would be. |
I would put this in datetimelike, numeric is for well, numeric types! this is sort of an arbitrary split but makes each section shorter |
doc/source/whatsnew/v0.23.0.txt
Outdated
@@ -446,6 +447,9 @@ Numeric | |||
- Bug in :class:`Index` multiplication and division methods where operating with a ``Series`` would return an ``Index`` object instead of a ``Series`` object (:issue:`19042`) | |||
- Bug in the :class:`DataFrame` constructor in which data containing very large positive or very large negative numbers was causing ``OverflowError`` (:issue:`18584`) | |||
- Bug in :class:`Index` constructor with ``dtype='uint64'`` where int-like floats were not coerced to :class:`UInt64Index` (:issue:`18400`) | |||
- Bug in :class:`Index` multiplication and division methods where operating with a ``Series`` would return an ``Index`` object instead of a ``Series`` object (:issue:`19042`) | |||
- Multiplication of :class:`TimedeltaIndex` by ``TimedeltaIndex`` will now raise ``TypeError`` instead of raising ``ValueError`` in cases of length mis-match (:issue`19333`) |
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.
1st one ok, other 2 in datetimelike section
pandas/tests/indexes/test_numeric.py
Outdated
@@ -26,6 +26,36 @@ def full_like(array, value): | |||
return ret | |||
|
|||
|
|||
class TestIndexArithmetic(object): | |||
@pytest.mark.parametrize('index', [pd.Int64Index(range(1, 11)), |
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.
can you add the issue number as a comment (or PR number if no issue)
pandas/tests/indexes/test_numeric.py
Outdated
class TestIndexArithmetic(object): | ||
@pytest.mark.parametrize('index', [pd.Int64Index(range(1, 11)), | ||
pd.UInt64Index(range(1, 11)), | ||
pd.Float64Index(range(1, 11)), |
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.
is this how we are importing in this module, e.g. pd.*
? usually we don't do this (its ok whichever, just want to be consistent)
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.
Looks like I'm being inconsistent here, will change.
expected = pd.TimedeltaIndex(['1 Day', '12 Hours']) | ||
|
||
result = scalar_td / index | ||
tm.assert_index_equal(result, expected) |
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.
can you also test that the commute raises here
@@ -297,7 +297,7 @@ def test_dti_mul_dti_raises(self): | |||
|
|||
def test_dti_mul_too_short_raises(self): | |||
idx = self._holder(np.arange(5, dtype='int64')) | |||
with pytest.raises(ValueError): |
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.
why did this change?
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.
Because the problem is now caught in TimedeltaIndex when checking what it is operating against, whereas before the problem was caught in numpy when trying to operate on differently-sized arrays.
pandas/tests/indexes/test_numeric.py
Outdated
pd.UInt64Index(range(1, 3)), | ||
pd.Float64Index(range(1, 3)), | ||
pd.RangeIndex(1, 3)]) | ||
@pytest.mark.parametrize('scalar_td', [Timedelta(days=1), |
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 tests really belong with the scalar timedelta tests I think
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.
Yah I thought about that and eventually decided that since the affected code was in the Index class, the test belonged in the Index tests. But either way works for me.
pandas/tests/indexes/test_numeric.py
Outdated
@@ -26,6 +26,36 @@ def full_like(array, value): | |||
return ret | |||
|
|||
|
|||
class TestIndexArithmetic(object): |
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.
rename this class its index with timedelta scalar
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.
add a comment. future readers are going to have no idea of where to find tests
Any idea what's special about the circleCI setup? I can't replicate the error there. |
Codecov Report
@@ Coverage Diff @@
## master #19333 +/- ##
==========================================
- Coverage 91.61% 91.59% -0.03%
==========================================
Files 150 150
Lines 48892 48911 +19
==========================================
+ Hits 44792 44798 +6
- Misses 4100 4113 +13
Continue to review full report at Codecov.
|
@gfyoung any wisdom to offer about what makes circleci config special? |
@jbrockmendel : I wish 😉 I've generally found Circle and AppVeyor to be more PITA than Travis due to weird failures like these. AFAIK, Travis and Circle are quite similar, so unless you have some kind of flakiness in your tests, I'm not 100% sure why you are getting these results. |
@gfyoung OK thanks. I'd rebase and re-push and hope that it sorts itself out, but don't want to put the strain on Travis. |
@jbrockmendel : No worries. I'm still kind of perplexed why Circle gets the completely wrong result when doing such a simple operation. |
looks fine. ping when all green. |
look on circleci on how to do this |
https://circleci.com/docs/2.0/ssh-access-jobs/ Looks like I need to send you a public key and have you authorize it for me to debug. |
you simply need to sign up on CircleCI, then you can run personal builds. |
@gfyoung I made it onto CircleCI but couldn't replicate the test failure. Can I impose on you to give it a try? There's a beer and a high-five in it for you if that helps. |
@jbrockmendel : Can you push those to me on GitHub? 😄 I restarted both AppVeyor and Circle for you. That being said, not sure yet what's causing the discrepancy. Might be something architecturally-related (e.g. |
Oh is it a 32 bit build thats broken? I hadn't noticed that. |
values, other = other, values | ||
|
||
with np.errstate(all='ignore'): | ||
result = op(values, 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.
can you add some comments (or expand the top ones), this code does a lot
small comments, is there an issue about this (or just PR)? rebase and ping on green. |
Just the PR I think. My attempt to SSH into CircleCI to debug the weird failing test failed. I'll try again at some point, hoping a fresh pair of eyeballs takes a crack at it in the interim. |
I think I got this fixed, reopening. |
what did it turn out to be? |
I'll open an issue for the underlying cause because it might cause problems elsewhere: in sufficiently old numpy (the build that caught it used 1.9.2) we see the following:
As a result |
we do't need a new issue for this. see my comments there. rebase and I'll have a look. |
there are many places in the code base where this is handled. This is the point of needing to check for timedeta before its checked for integer. |
Rebase accomplished. |
thanks! hey sometimes my stubborness pay off ..... thanks for sticking with it! |
Fixes the following current behavior for each of the numeric index classes and each of the basic timedelta-like scalars:
git diff upstream/master -u -- "*.py" | flake8 --diff