-
-
Notifications
You must be signed in to change notification settings - Fork 18k
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/TST/REF: Datetimelike Arithmetic Methods #23215
Merged
Merged
Changes from 40 commits
Commits
Show all changes
49 commits
Select commit
Hold shift + click to select a range
dc2280f
Make arithmetic code dispatch less redundant, fix datetime64 addition…
jbrockmendel 37728ff
remove unnecessary nat_new
jbrockmendel 15ad0a6
Fix interpretation of NaT
jbrockmendel 94f1745
move test
jbrockmendel bf5e2fb
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 3bdf104
whatsnew, fix dropped timezone
jbrockmendel 982ea30
remove comment
jbrockmendel d046038
Add GH references
jbrockmendel a0c1a85
remove unused imports
jbrockmendel 33d82b3
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 8a7c249
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 8e57fd8
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel b932121
dummy commit to force CI
jbrockmendel 9f3b18d
Fix bug in adding DateOffset to PeriodIndex, Series, Frame
jbrockmendel 7a8232e
Dummy commit to force CI
jbrockmendel a743f74
revert tracebackhide
jbrockmendel 0693196
Merge branch 'arith' of https://github.com/jbrockmendel/pandas into a…
jbrockmendel 29d91af
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel af4872e
comment and reversion
jbrockmendel 6707032
revert to simpler version
jbrockmendel 18ef26d
Move overriding of addsub_int_array to PeriodArray
jbrockmendel 60f7f8d
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 9372423
correct docstrings
jbrockmendel 2a6268e
comments and assertions
jbrockmendel 777f4d9
More explicit names for array/scalar add/sub methods
jbrockmendel ee885c8
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 5f231b2
oo optimization fixup
jbrockmendel 0214a9e
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel fbee9f5
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel f7cf3d9
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel d799d8e
Dummy commit to force CI
jbrockmendel 82df39c
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 8cf614b
change default fill_value for maybe_mask_results
jbrockmendel a45734a
Merge branch 'arith' of https://github.com/jbrockmendel/pandas into a…
jbrockmendel fb007cb
Make docstring extra explicit
jbrockmendel 1d3fd48
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel aecfef7
prettify docstrings
jbrockmendel dade955
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel a6eb01c
fixup super usage
jbrockmendel acf1f74
flesh out TODO comment
jbrockmendel e89e3ef
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel d306277
move test for moved method
jbrockmendel f6e4073
Fixup name
jbrockmendel 9146a72
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 4e4b9ed
change NotImplementedError to TypeError
jbrockmendel f35b3b6
Fix add_delta_tdi return type; docstrings
jbrockmendel 87e07ef
Merge branch 'arith' of https://github.com/jbrockmendel/pandas into a…
jbrockmendel 343ee30
Merge branch 'master' of https://github.com/pandas-dev/pandas into arith
jbrockmendel 0466b9c
docstring edit, rename
jbrockmendel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -221,7 +221,7 @@ def hasnans(self): | |
""" return if I have any nans; enables various perf speedups """ | ||
return self._isnan.any() | ||
|
||
def _maybe_mask_results(self, result, fill_value=None, convert=None): | ||
def _maybe_mask_results(self, result, fill_value=iNaT, convert=None): | ||
""" | ||
Parameters | ||
---------- | ||
|
@@ -246,27 +246,6 @@ def _maybe_mask_results(self, result, fill_value=None, convert=None): | |
result[self._isnan] = fill_value | ||
return result | ||
|
||
def _nat_new(self, box=True): | ||
""" | ||
Return Array/Index or ndarray filled with NaT which has the same | ||
length as the caller. | ||
|
||
Parameters | ||
---------- | ||
box : boolean, default True | ||
- If True returns a Array/Index as the same as caller. | ||
- If False returns ndarray of np.int64. | ||
""" | ||
result = np.zeros(len(self), dtype=np.int64) | ||
result.fill(iNaT) | ||
if not box: | ||
return result | ||
|
||
attribs = self._get_attributes_dict() | ||
if not is_period_dtype(self): | ||
attribs['freq'] = None | ||
return self._simple_new(result, **attribs) | ||
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 is only used once outside of tests. Much less verbose to inline. 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. hah I just made a comment on PeriodArray about re-using this. |
||
|
||
# ------------------------------------------------------------------ | ||
# Frequency Properties/Methods | ||
|
||
|
@@ -346,22 +325,56 @@ def _validate_frequency(cls, index, freq, **kwargs): | |
# ------------------------------------------------------------------ | ||
# Arithmetic Methods | ||
|
||
def _add_datelike(self, other): | ||
def _add_datetimelike_scalar(self, other): | ||
# Overriden by TimedeltaArray | ||
raise TypeError("cannot add {cls} and {typ}" | ||
.format(cls=type(self).__name__, | ||
typ=type(other).__name__)) | ||
|
||
def _sub_datelike(self, other): | ||
raise com.AbstractMethodError(self) | ||
_add_datetime_arraylike = _add_datetimelike_scalar | ||
|
||
def _sub_datetimelike_scalar(self, other): | ||
# Overridden by DatetimeArray | ||
assert other is not NaT | ||
raise TypeError("cannot subtract a datelike from a {cls}" | ||
.format(cls=type(self).__name__)) | ||
|
||
_sub_datetime_arraylike = _sub_datetimelike_scalar | ||
|
||
def _sub_period(self, other): | ||
return NotImplemented | ||
# Overriden by PeriodArray | ||
raise TypeError("cannot subtract Period from a {cls}" | ||
.format(cls=type(self).__name__)) | ||
jorisvandenbossche marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def _add_offset(self, offset): | ||
raise com.AbstractMethodError(self) | ||
|
||
def _add_delta(self, other): | ||
return NotImplemented | ||
""" | ||
Add a timedelta-like, Tick or TimedeltaIndex-like object | ||
to self, yielding an int64 numpy array | ||
|
||
Parameters | ||
---------- | ||
delta : {timedelta, np.timedelta64, Tick, | ||
TimedeltaIndex, ndarray[timedelta64]} | ||
|
||
Returns | ||
------- | ||
result : ndarray[int64] | ||
|
||
Notes | ||
----- | ||
The result's name is set outside of _add_delta by the calling | ||
method (__add__ or __sub__), if necessary (i.e. for Indexes). | ||
""" | ||
if isinstance(other, (Tick, timedelta, np.timedelta64)): | ||
new_values = self._add_delta_td(other) | ||
elif is_timedelta64_dtype(other): | ||
# ndarray[timedelta64] or TimedeltaArray/index | ||
new_values = self._add_delta_tdi(other) | ||
|
||
return new_values | ||
|
||
def _add_delta_td(self, other): | ||
""" | ||
|
@@ -371,16 +384,15 @@ def _add_delta_td(self, other): | |
inc = delta_to_nanoseconds(other) | ||
new_values = checked_add_with_arr(self.asi8, inc, | ||
arr_mask=self._isnan).view('i8') | ||
if self.hasnans: | ||
new_values[self._isnan] = iNaT | ||
new_values = self._maybe_mask_results(new_values) | ||
return new_values.view('i8') | ||
|
||
def _add_delta_tdi(self, other): | ||
""" | ||
Add a delta of a TimedeltaIndex | ||
return the i8 result view | ||
""" | ||
if not len(self) == len(other): | ||
if len(self) != len(other): | ||
raise ValueError("cannot add indices of unequal length") | ||
|
||
if isinstance(other, np.ndarray): | ||
|
@@ -407,7 +419,9 @@ def _add_nat(self): | |
|
||
# GH#19124 pd.NaT is treated like a timedelta for both timedelta | ||
# and datetime dtypes | ||
return self._nat_new(box=True) | ||
result = np.zeros(len(self), dtype=np.int64) | ||
result.fill(iNaT) | ||
return self._shallow_copy(result, freq=None) | ||
|
||
def _sub_nat(self): | ||
"""Subtract pd.NaT from self""" | ||
|
@@ -441,7 +455,7 @@ def _sub_period_array(self, other): | |
.format(dtype=other.dtype, | ||
cls=type(self).__name__)) | ||
|
||
if not len(self) == len(other): | ||
if len(self) != len(other): | ||
raise ValueError("cannot subtract arrays/indices of " | ||
"unequal length") | ||
if self.freq != other.freq: | ||
|
@@ -473,6 +487,8 @@ def _addsub_int_array(self, other, op): | |
------- | ||
result : same class as self | ||
""" | ||
# _addsub_int_array is overriden by PeriodArray | ||
assert not is_period_dtype(self) | ||
assert op in [operator.add, operator.sub] | ||
|
||
if self.freq is None: | ||
|
@@ -613,7 +629,7 @@ def __add__(self, other): | |
# specifically _not_ a Tick | ||
result = self._add_offset(other) | ||
elif isinstance(other, (datetime, np.datetime64)): | ||
result = self._add_datelike(other) | ||
result = self._add_datetimelike_scalar(other) | ||
elif lib.is_integer(other): | ||
# This check must come after the check for np.timedelta64 | ||
# as is_integer returns True for these | ||
|
@@ -628,7 +644,7 @@ def __add__(self, other): | |
result = self._addsub_offset_array(other, operator.add) | ||
elif is_datetime64_dtype(other) or is_datetime64tz_dtype(other): | ||
# DatetimeIndex, ndarray[datetime64] | ||
return self._add_datelike(other) | ||
return self._add_datetime_arraylike(other) | ||
elif is_integer_dtype(other): | ||
result = self._addsub_int_array(other, operator.add) | ||
elif is_float_dtype(other): | ||
|
@@ -671,7 +687,7 @@ def __sub__(self, other): | |
# specifically _not_ a Tick | ||
result = self._add_offset(-other) | ||
elif isinstance(other, (datetime, np.datetime64)): | ||
result = self._sub_datelike(other) | ||
result = self._sub_datetimelike_scalar(other) | ||
elif lib.is_integer(other): | ||
# This check must come after the check for np.timedelta64 | ||
# as is_integer returns True for these | ||
|
@@ -688,7 +704,7 @@ def __sub__(self, other): | |
result = self._addsub_offset_array(other, operator.sub) | ||
elif is_datetime64_dtype(other) or is_datetime64tz_dtype(other): | ||
# DatetimeIndex, ndarray[datetime64] | ||
result = self._sub_datelike(other) | ||
result = self._sub_datetime_arraylike(other) | ||
elif is_period_dtype(other): | ||
# PeriodIndex | ||
result = self._sub_period_array(other) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 update the doc-string for fill_value