-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
REF: move more methods to EAMixins #21782
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 all commits
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 |
---|---|---|
|
@@ -107,6 +107,32 @@ def offset(self, value): | |
warnings.warn(msg, FutureWarning, stacklevel=2) | ||
self.freq = value | ||
|
||
# ---------------------------------------------------------------- | ||
# Array-like Methods | ||
|
||
def __iter__(self): | ||
""" | ||
Return an iterator over the boxed values | ||
|
||
Yields | ||
------- | ||
tstamp : Timestamp | ||
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. changed from existing version on DatetimeIndex where it says
|
||
""" | ||
|
||
# convert in chunks of 10k for efficiency | ||
data = self.asi8 | ||
length = len(self) | ||
chunksize = 10000 | ||
chunks = int(length / chunksize) + 1 | ||
for i in range(chunks): | ||
start_i = i * chunksize | ||
end_i = min((i + 1) * chunksize, length) | ||
converted = tslib.ints_to_pydatetime(data[start_i:end_i], | ||
tz=self.tz, freq=self.freq, | ||
box="timestamp") | ||
for v in converted: | ||
yield v | ||
|
||
# ----------------------------------------------------------------- | ||
# Comparison Methods | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,28 @@ | ||
# -*- coding: utf-8 -*- | ||
from datetime import timedelta | ||
|
||
import numpy as np | ||
|
||
from pandas._libs import tslib | ||
from pandas._libs.tslib import Timedelta, NaT | ||
from pandas._libs.tslibs.fields import get_timedelta_field | ||
|
||
from pandas import compat | ||
|
||
from pandas.core.dtypes.common import _TD_DTYPE | ||
from pandas.core.dtypes.generic import ABCSeries | ||
from pandas.core.dtypes.missing import isna | ||
|
||
from pandas.tseries.offsets import Tick | ||
|
||
from .datetimelike import DatetimeLikeArrayMixin | ||
|
||
|
||
def _is_convertible_to_td(key): | ||
return isinstance(key, (Tick, timedelta, | ||
np.timedelta64, compat.string_types)) | ||
|
||
|
||
def _field_accessor(name, alias, docstring=None): | ||
def f(self): | ||
values = self.asi8 | ||
|
@@ -48,9 +60,53 @@ def _sub_datelike(self, other): | |
raise TypeError("cannot subtract a datelike from a {cls}" | ||
.format(cls=type(self).__name__)) | ||
|
||
def _evaluate_with_timedelta_like(self, other, op): | ||
if isinstance(other, ABCSeries): | ||
# GH#19042 | ||
return NotImplemented | ||
|
||
opstr = '__{opname}__'.format(opname=op.__name__).replace('__r', '__') | ||
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. we ought to have a method to do exactly this in the base ExtensionOpsMixin (but for later cleanup) |
||
# allow division by a timedelta | ||
if opstr in ['__div__', '__truediv__', '__floordiv__']: | ||
if _is_convertible_to_td(other): | ||
other = Timedelta(other) | ||
if isna(other): | ||
raise NotImplementedError( | ||
"division by pd.NaT not implemented") | ||
|
||
i8 = self.asi8 | ||
left, right = i8, other.value | ||
|
||
if opstr in ['__floordiv__']: | ||
result = op(left, right) | ||
else: | ||
result = op(left, np.float64(right)) | ||
result = self._maybe_mask_results(result, convert='float64') | ||
return result | ||
|
||
return NotImplemented | ||
|
||
# ---------------------------------------------------------------- | ||
# Conversion Methods - Vectorized analogues of Timedelta methods | ||
|
||
def total_seconds(self): | ||
""" | ||
Return total duration of each element expressed in seconds. | ||
|
||
This method is available directly on TimedeltaArray, TimedeltaIndex | ||
and on Series containing timedelta values under the ``.dt`` namespace. | ||
|
||
Returns | ||
------- | ||
seconds : ndarray, Float64Index, or Series | ||
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. updated docstring to include ndarray |
||
When the calling object is a TimedeltaArray, the return type | ||
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 make this in to a list of these return values |
||
is ndarray. When the calling object is a TimedeltaIndex, | ||
the return type is a Float64Index. When the calling object | ||
is a Series, the return type is Series of type `float64` whose | ||
index is the same as the original. | ||
""" | ||
return self._maybe_mask_results(1e-9 * self.asi8) | ||
|
||
def to_pytimedelta(self): | ||
""" | ||
Return Timedelta Array/Index as object ndarray of datetime.timedelta | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,6 @@ | |
from pandas._libs.tslibs.period import (Period, IncompatibleFrequency, | ||
DIFFERENT_FREQ_INDEX, | ||
_validate_end_alias, _quarter_to_myear) | ||
from pandas._libs.tslibs.fields import isleapyear_arr | ||
from pandas._libs.tslibs import resolution, period | ||
from pandas._libs.tslibs.timedeltas import delta_to_nanoseconds | ||
|
||
|
@@ -625,11 +624,6 @@ def asfreq(self, freq=None, how='E'): | |
days_in_month = _wrap_field_accessor('days_in_month') | ||
daysinmonth = days_in_month | ||
|
||
@property | ||
def is_leap_year(self): | ||
""" Logical indicating if the date belongs to a leap year """ | ||
return isleapyear_arr(np.asarray(self.year)) | ||
|
||
@property | ||
def start_time(self): | ||
return self.to_timestamp(how='start') | ||
|
@@ -702,16 +696,7 @@ def _add_delta(self, other): | |
def _sub_period(self, other): | ||
# If the operation is well-defined, we return an object-Index | ||
# of DateOffsets. Null entries are filled with pd.NaT | ||
if self.freq != other.freq: | ||
msg = DIFFERENT_FREQ_INDEX.format(self.freqstr, other.freqstr) | ||
raise IncompatibleFrequency(msg) | ||
|
||
asi8 = self.asi8 | ||
new_data = asi8 - other.ordinal | ||
new_data = np.array([self.freq * x for x in new_data]) | ||
|
||
if self.hasnans: | ||
new_data[self._isnan] = tslib.NaT | ||
new_data = PeriodArrayMixin._sub_period(self, other) | ||
|
||
# TODO: Should name=self.name be passed here? | ||
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 think the answer to this is a) yes, but b) if we remove this method entirely then when the inherited method is called from |
||
return Index(new_data) | ||
|
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.
so for future, any methods that we implement in the sub classes but not here, should be an AbstractMethodError (not specific to this comment, just generally)