-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
dispatch Series[datetime64] comparison ops to DatetimeIndex #19800
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
Changes from 8 commits
1990e3f
f48e6d5
bd909b0
003c4ff
f942be9
59c96e8
25534c6
3d15998
db487e8
ba290ab
f8d5bdd
9e59598
b618a82
35db0a2
3911541
ff51634
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 |
---|---|---|
|
@@ -10,8 +10,7 @@ | |
import numpy as np | ||
import pandas as pd | ||
|
||
from pandas._libs import (lib, index as libindex, | ||
algos as libalgos) | ||
from pandas._libs import lib, algos as libalgos | ||
|
||
from pandas import compat | ||
from pandas.util._decorators import Appender | ||
|
@@ -944,24 +943,20 @@ def na_op(x, y): | |
# integer comparisons | ||
|
||
# we have a datetime/timedelta and may need to convert | ||
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. Is this comment still correct? Or is it only 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. It's only for |
||
assert not needs_i8_conversion(x) | ||
mask = None | ||
if (needs_i8_conversion(x) or | ||
(not is_scalar(y) and needs_i8_conversion(y))): | ||
|
||
if is_scalar(y): | ||
mask = isna(x) | ||
y = libindex.convert_scalar(x, com._values_from_object(y)) | ||
else: | ||
mask = isna(x) | isna(y) | ||
y = y.view('i8') | ||
if not is_scalar(y) and needs_i8_conversion(y): | ||
mask = isna(x) | isna(y) | ||
y = y.view('i8') | ||
x = x.view('i8') | ||
|
||
try: | ||
method = getattr(x, name, None) | ||
if method is not None: | ||
with np.errstate(all='ignore'): | ||
result = getattr(x, name)(y) | ||
result = method(y) | ||
if result is NotImplemented: | ||
raise TypeError("invalid type comparison") | ||
except AttributeError: | ||
else: | ||
result = op(x, y) | ||
|
||
if mask is not None and mask.any(): | ||
|
@@ -991,6 +986,12 @@ def wrapper(self, other, axis=None): | |
return self._constructor(res_values, index=self.index, | ||
name=res_name) | ||
|
||
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 add some comments at various places |
||
if is_datetime64_dtype(self) or is_datetime64tz_dtype(self): | ||
res_values = dispatch_to_index_op(op, self, other, | ||
pd.DatetimeIndex) | ||
return self._constructor(res_values, index=self.index, | ||
name=res_name) | ||
|
||
elif is_timedelta64_dtype(self): | ||
res_values = dispatch_to_index_op(op, self, other, | ||
pd.TimedeltaIndex) | ||
|
@@ -1008,8 +1009,7 @@ def wrapper(self, other, axis=None): | |
elif isinstance(other, (np.ndarray, pd.Index)): | ||
# do not check length of zerodim array | ||
# as it will broadcast | ||
if (not is_scalar(lib.item_from_zerodim(other)) and | ||
len(self) != len(other)): | ||
if other.ndim != 0 and len(self) != len(other): | ||
raise ValueError('Lengths must match to compare') | ||
|
||
res_values = na_op(self.values, np.asarray(other)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,7 @@ | |
|
||
import pytest | ||
|
||
from datetime import datetime, date | ||
from datetime import datetime | ||
import numpy as np | ||
import pandas as pd | ||
import operator as op | ||
|
@@ -349,7 +349,7 @@ def test_loc_datetime_length_one(self): | |
|
||
@pytest.mark.parametrize('datetimelike', [ | ||
Timestamp('20130101'), datetime(2013, 1, 1), | ||
date(2013, 1, 1), np.datetime64('2013-01-01T00:00', 'ns')]) | ||
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. Remind me, why was this test removed? 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. b/c ATM 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 add a separate test for date (I know its wrong, but assert that it is wrong) |
||
np.datetime64('2013-01-01T00:00', 'ns')]) | ||
@pytest.mark.parametrize('op,expected', [ | ||
(op.lt, [True, False, False, False]), | ||
(op.le, [True, True, False, False]), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ | |
import pandas as pd | ||
import pandas.compat as compat | ||
from pandas.core.dtypes.common import ( | ||
is_object_dtype, is_datetimetz, | ||
is_object_dtype, is_datetimetz, is_datetime64_dtype, | ||
needs_i8_conversion) | ||
import pandas.util.testing as tm | ||
from pandas import (Series, Index, DatetimeIndex, TimedeltaIndex, | ||
|
@@ -296,14 +296,21 @@ def test_none_comparison(self): | |
# result = None != o # noqa | ||
# assert result.iat[0] | ||
# assert result.iat[1] | ||
if (is_datetime64_dtype(o) or is_datetimetz(o)): | ||
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. this might be simpler to separate out into datetimelike and non-datetimelike 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. as in separate tests? 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. yes, all of these ifs make it hard to read 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 whole test should be parametrized, and there 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 that's fine |
||
# Following DatetimeIndex (and Timestamp) convention, | ||
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. I assume inequality comparison raising is tested elsewhere? Or should we assert that in an 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. Forgot to port that test from the previous PR, good catch. |
||
# inequality comparisons with Series[datetime64] raise | ||
with pytest.raises(TypeError): | ||
None > o | ||
with pytest.raises(TypeError): | ||
o > None | ||
else: | ||
result = None > o | ||
assert not result.iat[0] | ||
assert not result.iat[1] | ||
|
||
result = None > o | ||
assert not result.iat[0] | ||
assert not result.iat[1] | ||
|
||
result = o < None | ||
assert not result.iat[0] | ||
assert not result.iat[1] | ||
result = o < None | ||
assert not result.iat[0] | ||
assert not result.iat[1] | ||
|
||
def test_ndarray_compat_properties(self): | ||
|
||
|
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.
huh?
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.
The last few commits have been troubleshooting appveyor-only errors. Based on this line in the logs I guessed it was a 32-bit build, but now I see a "64" in their so am back to no-clue:
It looks like in this build
pandas.tests.frame.test_operators.TestDataFrameOperators.test_comparison_invalid
is trying to compare aDatetimeIndex
with aSeries[int32]
. In other builds the same testcompares with a
Series[int64]
and goes through OK. The exact error varies depending on which commit we're looking at, but the pertinent one is a call toother.values.view('i8')
which raisesValueError
with aSeries[int32]
.Note that
pd.date_range('2016-01-01', periods=3) == pd.Series([0, 1, 2], dtype='i4')
raises locally, so the appveyor-specific behavior is whatever is causing it to pass an int32 series when everything else passes an int64.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 it a bug then, something is assuming int64 but getting int32, if you want to attach the last:
I get why this is not allowed, but its a bit annoying.