Skip to content

DTA Followups - remove redundant methods #24577

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

Merged
merged 4 commits into from
Jan 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 5 additions & 70 deletions pandas/core/arrays/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@
from pandas.util._validators import validate_fillna_kwargs

from pandas.core.dtypes.common import (
is_bool_dtype, is_categorical_dtype, is_datetime64_any_dtype,
is_datetime64_dtype, is_datetime64tz_dtype, is_datetime_or_timedelta_dtype,
is_dtype_equal, is_extension_array_dtype, is_float_dtype, is_integer_dtype,
is_list_like, is_object_dtype, is_offsetlike, is_period_dtype,
is_string_dtype, is_timedelta64_dtype, is_unsigned_integer_dtype,
needs_i8_conversion, pandas_dtype)
is_categorical_dtype, is_datetime64_any_dtype, is_datetime64_dtype,
is_datetime64tz_dtype, is_datetime_or_timedelta_dtype, is_dtype_equal,
is_extension_array_dtype, is_float_dtype, is_integer_dtype, is_list_like,
is_object_dtype, is_offsetlike, is_period_dtype, is_string_dtype,
is_timedelta64_dtype, is_unsigned_integer_dtype, pandas_dtype)
from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCSeries
from pandas.core.dtypes.inference import is_array_like
from pandas.core.dtypes.missing import isna
Expand All @@ -40,32 +39,6 @@
from .base import ExtensionArray, ExtensionOpsMixin


def _make_comparison_op(cls, op):
# TODO: share code with indexes.base version? Main difference is that
# the block for MultiIndex was removed here.
def cmp_method(self, other):
if isinstance(other, ABCDataFrame):
return NotImplemented

if needs_i8_conversion(self) and needs_i8_conversion(other):
# we may need to directly compare underlying
# representations
return self._evaluate_compare(other, op)

# numpy will show a DeprecationWarning on invalid elementwise
# comparisons, this will raise in the future
with warnings.catch_warnings(record=True):
warnings.filterwarnings("ignore", "elementwise", FutureWarning)
with np.errstate(all='ignore'):
result = op(self._data, np.asarray(other))

return result

name = '__{name}__'.format(name=op.__name__)
# TODO: docstring?
return compat.set_function_name(cmp_method, name, cls)


class AttributesMixin(object):

@property
Expand Down Expand Up @@ -1358,41 +1331,6 @@ def __isub__(self, other):
# --------------------------------------------------------------
# Comparison Methods

# Called by _add_comparison_methods defined in ExtensionOpsMixin
_create_comparison_method = classmethod(_make_comparison_op)

def _evaluate_compare(self, other, op):
"""
We have been called because a comparison between
8 aware arrays. numpy will warn about NaT comparisons
"""
# Called by comparison methods when comparing datetimelike
# with datetimelike

if not isinstance(other, type(self)):
# coerce to a similar object
if not is_list_like(other):
# scalar
other = [other]
elif lib.is_scalar(lib.item_from_zerodim(other)):
# ndarray scalar
other = [other.item()]
other = type(self)._from_sequence(other)

# compare
result = op(self.asi8, other.asi8)

# technically we could support bool dtyped Index
# for now just return the indexing array directly
mask = (self._isnan) | (other._isnan)

filler = iNaT
if is_bool_dtype(result):
filler = False

result[mask] = filler
return result

def _ensure_localized(self, arg, ambiguous='raise', nonexistent='raise',
from_utc=False):
"""
Expand Down Expand Up @@ -1493,9 +1431,6 @@ def max(self, axis=None, skipna=True, *args, **kwargs):
return self._box_func(result)


DatetimeLikeArrayMixin._add_comparison_ops()


# -------------------------------------------------------------------
# Shared Constructor Helpers

Expand Down
7 changes: 3 additions & 4 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
_midnight = time(0, 0)


def _to_m8(key, tz=None):
def _to_M8(key, tz=None):
Copy link
Contributor

Choose a reason for hiding this comment

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

isn't the conversion just (line 50)

In [1]: from pandas._libs.tslibs import conversion

In [2]: ts = pd.Timestamp('20181001', tz='UTC')

In [3]: np.int64(conversion.pydt_to_i8(ts)).view('M8[ns]')
Out[3]: numpy.datetime64('2018-10-01T00:00:00.000000000')

In [5]: ts.to_datetime64()
Out[5]: numpy.datetime64('2018-10-01T00:00:00.000000000')

Copy link
Contributor

Choose a reason for hiding this comment

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

this routine should really just be in conversion.pyx

Copy link
Member Author

Choose a reason for hiding this comment

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

I’m hoping we can do something clever see #24576. Not sure we are internally consistent enough to do that yet though.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok

"""
Timestamp-like => dt64
"""
Expand Down Expand Up @@ -96,7 +96,6 @@ def _dt_array_cmp(cls, op):
nat_result = True if opname == '__ne__' else False

def wrapper(self, other):
meth = getattr(dtl.DatetimeLikeArrayMixin, opname)
# TODO: return NotImplemented for Series / Index and let pandas unbox
# Right now, returning NotImplemented for Index fails because we
# go into the index implementation, which may be a bug?
Expand All @@ -109,7 +108,7 @@ def wrapper(self, other):
self._assert_tzawareness_compat(other)

try:
other = _to_m8(other, tz=self.tz)
other = _to_M8(other, tz=self.tz)
except ValueError:
# string that cannot be parsed to Timestamp
return ops.invalid_comparison(self, other, op)
Expand Down Expand Up @@ -158,7 +157,7 @@ def wrapper(self, other):
# or an object-dtype ndarray
other = type(self)._from_sequence(other)

result = meth(self, other)
result = op(self.view('i8'), other.view('i8'))
o_mask = other._isnan

result = com.values_from_object(result)
Expand Down
20 changes: 3 additions & 17 deletions pandas/core/arrays/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@
_BAD_DTYPE = "dtype {dtype} cannot be converted to timedelta64[ns]"


def _to_m8(key):
"""
Timedelta-like => dt64
"""
if not isinstance(key, Timedelta):
# this also converts strings
key = Timedelta(key)

# return an type that can be compared
return np.int64(key.value).view(_TD_DTYPE)


def _is_convertible_to_td(key):
return isinstance(key, (Tick, timedelta,
np.timedelta64, compat.string_types))
Expand Down Expand Up @@ -75,17 +63,15 @@ def _td_array_cmp(cls, op):
opname = '__{name}__'.format(name=op.__name__)
nat_result = True if opname == '__ne__' else False

meth = getattr(dtl.DatetimeLikeArrayMixin, opname)

def wrapper(self, other):
if _is_convertible_to_td(other) or other is NaT:
try:
other = _to_m8(other)
other = Timedelta(other)
except ValueError:
# failed to parse as timedelta
return ops.invalid_comparison(self, other, op)

result = meth(self, other)
result = op(self.view('i8'), other.value)
if isna(other):
result.fill(nat_result)

Expand All @@ -101,7 +87,7 @@ def wrapper(self, other):
except (ValueError, TypeError):
return ops.invalid_comparison(self, other, op)

result = meth(self, other)
result = op(self.view('i8'), other.view('i8'))
result = com.values_from_object(result)

o_mask = np.array(isna(other))
Expand Down
14 changes: 2 additions & 12 deletions pandas/core/indexes/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
from pandas.util._decorators import Appender, cache_readonly, deprecate_kwarg

from pandas.core.dtypes.common import (
ensure_int64, is_bool_dtype, is_dtype_equal, is_float, is_integer,
is_list_like, is_period_dtype, is_scalar)
ensure_int64, is_dtype_equal, is_float, is_integer, is_list_like,
is_period_dtype, is_scalar)
from pandas.core.dtypes.generic import ABCIndex, ABCIndexClass, ABCSeries

from pandas.core import algorithms, ops
Expand Down Expand Up @@ -191,16 +191,6 @@ def wrapper(left, right):

return wrapper

@Appender(DatetimeLikeArrayMixin._evaluate_compare.__doc__)
def _evaluate_compare(self, other, op):
result = self._eadata._evaluate_compare(other, op)
if is_bool_dtype(result):
return result
try:
return Index(result)
except TypeError:
return result

def _ensure_localized(self, arg, ambiguous='raise', nonexistent='raise',
from_utc=False):
# See DatetimeLikeArrayMixin._ensure_localized.__doc__
Expand Down
8 changes: 4 additions & 4 deletions pandas/core/indexes/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from pandas.core.accessor import delegate_names
from pandas.core.arrays.datetimes import (
DatetimeArrayMixin as DatetimeArray, _to_m8, validate_tz_from_dtype)
DatetimeArrayMixin as DatetimeArray, _to_M8, validate_tz_from_dtype)
from pandas.core.base import _shared_docs
import pandas.core.common as com
from pandas.core.indexes.base import Index
Expand Down Expand Up @@ -405,7 +405,7 @@ def __setstate__(self, state):
def _convert_for_op(self, value):
""" Convert value to be insertable to ndarray """
if self._has_same_tz(value):
return _to_m8(value)
return _to_M8(value)
raise ValueError('Passed item and index have different timezone')

def _maybe_update_attributes(self, attrs):
Expand Down Expand Up @@ -1161,7 +1161,7 @@ def searchsorted(self, value, side='left', sorter=None):
if isinstance(value, (np.ndarray, Index)):
value = np.array(value, dtype=_NS_DTYPE, copy=False)
else:
value = _to_m8(value, tz=self.tz)
value = _to_M8(value, tz=self.tz)

return self.values.searchsorted(value, side=side)

Expand Down Expand Up @@ -1211,7 +1211,7 @@ def insert(self, loc, item):
freq = self.freq
elif (loc == len(self)) and item - self.freq == self[-1]:
freq = self.freq
item = _to_m8(item, tz=self.tz)
item = _to_M8(item, tz=self.tz)

try:
new_dates = np.concatenate((self[:loc].asi8, [item.view(np.int64)],
Expand Down
11 changes: 4 additions & 7 deletions pandas/core/indexes/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,6 @@ def _simple_new(cls, values, name=None, freq=None, **kwargs):
result._reset_identity()
return result

# ------------------------------------------------------------------------
# Wrapping PeriodArray

# ------------------------------------------------------------------------
# Data

Expand Down Expand Up @@ -416,6 +413,10 @@ def _mpl_repr(self):
# how to represent ourselves to matplotlib
return self.astype(object).values

@property
def _formatter_func(self):
return self.array._formatter(boxed=False)

# ------------------------------------------------------------------------
# Indexing

Expand Down Expand Up @@ -496,10 +497,6 @@ def __array_wrap__(self, result, context=None):
# cannot pass _simple_new as it is
return type(self)(result, freq=self.freq, name=self.name)

@property
def _formatter_func(self):
return self.array._formatter(boxed=False)

def asof_locs(self, where, mask):
"""
where : array of timestamps
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/indexes/timedeltas.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from pandas.core.accessor import delegate_names
from pandas.core.arrays import datetimelike as dtl
from pandas.core.arrays.timedeltas import (
TimedeltaArrayMixin as TimedeltaArray, _is_convertible_to_td, _to_m8)
TimedeltaArrayMixin as TimedeltaArray, _is_convertible_to_td)
from pandas.core.base import _shared_docs
import pandas.core.common as com
from pandas.core.indexes.base import Index, _index_shared_docs
Expand Down Expand Up @@ -614,7 +614,7 @@ def searchsorted(self, value, side='left', sorter=None):
if isinstance(value, (np.ndarray, Index)):
value = np.array(value, dtype=_TD_DTYPE, copy=False)
else:
value = _to_m8(value)
value = Timedelta(value).asm8.view(_TD_DTYPE)

return self.values.searchsorted(value, side=side, sorter=sorter)

Expand Down Expand Up @@ -664,7 +664,7 @@ def insert(self, loc, item):
freq = self.freq
elif (loc == len(self)) and item - self.freq == self[-1]:
freq = self.freq
item = _to_m8(item)
item = Timedelta(item).asm8.view(_TD_DTYPE)

try:
new_tds = np.concatenate((self[:loc].asi8, [item.view(np.int64)],
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/arithmetic/test_datetime64.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from pandas._libs.tslibs.conversion import localize_pydatetime
from pandas._libs.tslibs.offsets import shift_months

from pandas.core.indexes.datetimes import _to_m8
from pandas.core.indexes.datetimes import _to_M8

from pandas import (
Timestamp, Timedelta, Period, Series, date_range, NaT,
Expand Down Expand Up @@ -349,7 +349,7 @@ class TestDatetimeIndexComparisons(object):
def test_comparators(self, op):
index = tm.makeDateIndex(100)
element = index[len(index) // 2]
element = _to_m8(element)
element = _to_M8(element)

arr = np.array(index)
arr_result = op(arr, element)
Expand Down
Loading