diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index 33f71bcb2fef2..dcc6a5c836485 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -854,173 +854,159 @@ def _time_shift(self, periods, freq=None): return self._generate_range(start=start, end=end, periods=None, freq=self.freq) - @classmethod - def _add_datetimelike_methods(cls): - """ - add in the datetimelike methods (as we may have to override the - superclass) - """ + def __add__(self, other): + other = lib.item_from_zerodim(other) + if isinstance(other, (ABCSeries, ABCDataFrame)): + return NotImplemented - def __add__(self, other): - other = lib.item_from_zerodim(other) - if isinstance(other, (ABCSeries, ABCDataFrame)): - return NotImplemented - - # scalar others - elif other is NaT: - result = self._add_nat() - elif isinstance(other, (Tick, timedelta, np.timedelta64)): - result = self._add_delta(other) - elif isinstance(other, DateOffset): - # specifically _not_ a Tick - result = self._add_offset(other) - elif isinstance(other, (datetime, np.datetime64)): - 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 - maybe_integer_op_deprecated(self) - result = self._time_shift(other) - - # array-like others - elif is_timedelta64_dtype(other): - # TimedeltaIndex, ndarray[timedelta64] - result = self._add_delta(other) - elif is_offsetlike(other): - # Array/Index of DateOffset objects - result = self._addsub_offset_array(other, operator.add) - elif is_datetime64_dtype(other) or is_datetime64tz_dtype(other): - # DatetimeIndex, ndarray[datetime64] - return self._add_datetime_arraylike(other) - elif is_integer_dtype(other): - maybe_integer_op_deprecated(self) - result = self._addsub_int_array(other, operator.add) - elif is_float_dtype(other): - # Explicitly catch invalid dtypes - raise TypeError("cannot add {dtype}-dtype to {cls}" - .format(dtype=other.dtype, - cls=type(self).__name__)) - elif is_period_dtype(other): - # if self is a TimedeltaArray and other is a PeriodArray with - # a timedelta-like (i.e. Tick) freq, this operation is valid. - # Defer to the PeriodArray implementation. - # In remaining cases, this will end up raising TypeError. - return NotImplemented - elif is_extension_array_dtype(other): - # Categorical op will raise; defer explicitly - return NotImplemented - else: # pragma: no cover - return NotImplemented - - if is_timedelta64_dtype(result) and isinstance(result, np.ndarray): - from pandas.core.arrays import TimedeltaArrayMixin - # TODO: infer freq? - return TimedeltaArrayMixin(result) - return result + # scalar others + elif other is NaT: + result = self._add_nat() + elif isinstance(other, (Tick, timedelta, np.timedelta64)): + result = self._add_delta(other) + elif isinstance(other, DateOffset): + # specifically _not_ a Tick + result = self._add_offset(other) + elif isinstance(other, (datetime, np.datetime64)): + 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 + maybe_integer_op_deprecated(self) + result = self._time_shift(other) + + # array-like others + elif is_timedelta64_dtype(other): + # TimedeltaIndex, ndarray[timedelta64] + result = self._add_delta(other) + elif is_offsetlike(other): + # Array/Index of DateOffset objects + result = self._addsub_offset_array(other, operator.add) + elif is_datetime64_dtype(other) or is_datetime64tz_dtype(other): + # DatetimeIndex, ndarray[datetime64] + return self._add_datetime_arraylike(other) + elif is_integer_dtype(other): + maybe_integer_op_deprecated(self) + result = self._addsub_int_array(other, operator.add) + elif is_float_dtype(other): + # Explicitly catch invalid dtypes + raise TypeError("cannot add {dtype}-dtype to {cls}" + .format(dtype=other.dtype, + cls=type(self).__name__)) + elif is_period_dtype(other): + # if self is a TimedeltaArray and other is a PeriodArray with + # a timedelta-like (i.e. Tick) freq, this operation is valid. + # Defer to the PeriodArray implementation. + # In remaining cases, this will end up raising TypeError. + return NotImplemented + elif is_extension_array_dtype(other): + # Categorical op will raise; defer explicitly + return NotImplemented + else: # pragma: no cover + return NotImplemented - cls.__add__ = __add__ - - def __radd__(self, other): - # alias for __add__ - return self.__add__(other) - cls.__radd__ = __radd__ - - def __sub__(self, other): - other = lib.item_from_zerodim(other) - if isinstance(other, (ABCSeries, ABCDataFrame)): - return NotImplemented - - # scalar others - elif other is NaT: - result = self._sub_nat() - elif isinstance(other, (Tick, timedelta, np.timedelta64)): - result = self._add_delta(-other) - elif isinstance(other, DateOffset): - # specifically _not_ a Tick - result = self._add_offset(-other) - elif isinstance(other, (datetime, np.datetime64)): - 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 - maybe_integer_op_deprecated(self) - result = self._time_shift(-other) - - elif isinstance(other, Period): - result = self._sub_period(other) - - # array-like others - elif is_timedelta64_dtype(other): - # TimedeltaIndex, ndarray[timedelta64] - result = self._add_delta(-other) - elif is_offsetlike(other): - # Array/Index of DateOffset objects - result = self._addsub_offset_array(other, operator.sub) - elif is_datetime64_dtype(other) or is_datetime64tz_dtype(other): - # DatetimeIndex, ndarray[datetime64] - result = self._sub_datetime_arraylike(other) - elif is_period_dtype(other): - # PeriodIndex - result = self._sub_period_array(other) - elif is_integer_dtype(other): - maybe_integer_op_deprecated(self) - result = self._addsub_int_array(other, operator.sub) - elif isinstance(other, ABCIndexClass): - raise TypeError("cannot subtract {cls} and {typ}" - .format(cls=type(self).__name__, - typ=type(other).__name__)) - elif is_float_dtype(other): - # Explicitly catch invalid dtypes - raise TypeError("cannot subtract {dtype}-dtype from {cls}" - .format(dtype=other.dtype, - cls=type(self).__name__)) - elif is_extension_array_dtype(other): - # Categorical op will raise; defer explicitly - return NotImplemented - else: # pragma: no cover - return NotImplemented - - if is_timedelta64_dtype(result) and isinstance(result, np.ndarray): - from pandas.core.arrays import TimedeltaArrayMixin - # TODO: infer freq? - return TimedeltaArrayMixin(result) - return result + if is_timedelta64_dtype(result) and isinstance(result, np.ndarray): + from pandas.core.arrays import TimedeltaArrayMixin + # TODO: infer freq? + return TimedeltaArrayMixin(result) + return result + + def __radd__(self, other): + # alias for __add__ + return self.__add__(other) + + def __sub__(self, other): + other = lib.item_from_zerodim(other) + if isinstance(other, (ABCSeries, ABCDataFrame)): + return NotImplemented + + # scalar others + elif other is NaT: + result = self._sub_nat() + elif isinstance(other, (Tick, timedelta, np.timedelta64)): + result = self._add_delta(-other) + elif isinstance(other, DateOffset): + # specifically _not_ a Tick + result = self._add_offset(-other) + elif isinstance(other, (datetime, np.datetime64)): + 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 + maybe_integer_op_deprecated(self) + result = self._time_shift(-other) + + elif isinstance(other, Period): + result = self._sub_period(other) + + # array-like others + elif is_timedelta64_dtype(other): + # TimedeltaIndex, ndarray[timedelta64] + result = self._add_delta(-other) + elif is_offsetlike(other): + # Array/Index of DateOffset objects + result = self._addsub_offset_array(other, operator.sub) + elif is_datetime64_dtype(other) or is_datetime64tz_dtype(other): + # DatetimeIndex, ndarray[datetime64] + result = self._sub_datetime_arraylike(other) + elif is_period_dtype(other): + # PeriodIndex + result = self._sub_period_array(other) + elif is_integer_dtype(other): + maybe_integer_op_deprecated(self) + result = self._addsub_int_array(other, operator.sub) + elif isinstance(other, ABCIndexClass): + raise TypeError("cannot subtract {cls} and {typ}" + .format(cls=type(self).__name__, + typ=type(other).__name__)) + elif is_float_dtype(other): + # Explicitly catch invalid dtypes + raise TypeError("cannot subtract {dtype}-dtype from {cls}" + .format(dtype=other.dtype, + cls=type(self).__name__)) + elif is_extension_array_dtype(other): + # Categorical op will raise; defer explicitly + return NotImplemented + else: # pragma: no cover + return NotImplemented + + if is_timedelta64_dtype(result) and isinstance(result, np.ndarray): + from pandas.core.arrays import TimedeltaArrayMixin + # TODO: infer freq? + return TimedeltaArrayMixin(result) + return result + + def __rsub__(self, other): + if is_datetime64_dtype(other) and is_timedelta64_dtype(self): + # ndarray[datetime64] cannot be subtracted from self, so + # we need to wrap in DatetimeArray/Index and flip the operation + if not isinstance(other, DatetimeLikeArrayMixin): + # Avoid down-casting DatetimeIndex + from pandas.core.arrays import DatetimeArrayMixin + other = DatetimeArrayMixin(other) + return other - self + elif (is_datetime64_any_dtype(self) and hasattr(other, 'dtype') and + not is_datetime64_any_dtype(other)): + # GH#19959 datetime - datetime is well-defined as timedelta, + # but any other type - datetime is not well-defined. + raise TypeError("cannot subtract {cls} from {typ}" + .format(cls=type(self).__name__, + typ=type(other).__name__)) + elif is_period_dtype(self) and is_timedelta64_dtype(other): + # TODO: Can we simplify/generalize these cases at all? + raise TypeError("cannot subtract {cls} from {dtype}" + .format(cls=type(self).__name__, + dtype=other.dtype)) + return -(self - other) + + # FIXME: DTA/TDA/PA inplace methods should actually be inplace, GH#24115 + def __iadd__(self, other): + # alias for __add__ + return self.__add__(other) - cls.__sub__ = __sub__ - - def __rsub__(self, other): - if is_datetime64_dtype(other) and is_timedelta64_dtype(self): - # ndarray[datetime64] cannot be subtracted from self, so - # we need to wrap in DatetimeArray/Index and flip the operation - if not isinstance(other, DatetimeLikeArrayMixin): - # Avoid down-casting DatetimeIndex - from pandas.core.arrays import DatetimeArrayMixin - other = DatetimeArrayMixin(other) - return other - self - elif (is_datetime64_any_dtype(self) and hasattr(other, 'dtype') and - not is_datetime64_any_dtype(other)): - # GH#19959 datetime - datetime is well-defined as timedelta, - # but any other type - datetime is not well-defined. - raise TypeError("cannot subtract {cls} from {typ}" - .format(cls=type(self).__name__, - typ=type(other).__name__)) - elif is_period_dtype(self) and is_timedelta64_dtype(other): - # TODO: Can we simplify/generalize these cases at all? - raise TypeError("cannot subtract {cls} from {dtype}" - .format(cls=type(self).__name__, - dtype=other.dtype)) - return -(self - other) - cls.__rsub__ = __rsub__ - - def __iadd__(self, other): - # alias for __add__ - return self.__add__(other) - cls.__iadd__ = __iadd__ - - def __isub__(self, other): - # alias for __sub__ - return self.__sub__(other) - cls.__isub__ = __isub__ + def __isub__(self, other): + # alias for __sub__ + return self.__sub__(other) # -------------------------------------------------------------- # Comparison Methods diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index f453a9b734d17..119a6360c12f7 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1438,7 +1438,6 @@ def to_julian_date(self): DatetimeArrayMixin._add_comparison_ops() -DatetimeArrayMixin._add_datetimelike_methods() # ------------------------------------------------------------------- diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 4d466ef7281b7..1993440a2853b 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -830,7 +830,6 @@ def _values_for_argsort(self): PeriodArray._add_comparison_ops() -PeriodArray._add_datetimelike_methods() # ------------------------------------------------------------------- diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index f803144e0a78f..a393fe21ef6a8 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -734,7 +734,6 @@ def f(x): TimedeltaArrayMixin._add_comparison_ops() -TimedeltaArrayMixin._add_datetimelike_methods() # --------------------------------------------------------------------- diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 9d27d17014a56..2a8d58b8867b7 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -463,19 +463,6 @@ def __init__(self, data=None, index=None, columns=None, dtype=None, NDFrame.__init__(self, mgr, fastpath=True) - def _init_dict(self, data, index, columns, dtype=None): - """ - Segregate Series based on type and coerce into matrices. - Needs to handle a lot of exceptional cases. - """ - return init_dict(data, index, columns, dtype=dtype) - # TODO: Can we get rid of this as a method? - - def _init_ndarray(self, values, index, columns, dtype=None, copy=False): - # input must be a ndarray, list, Series, index - return init_ndarray(values, index, columns, dtype=dtype, copy=copy) - # TODO: can we just get rid of this as a method? - # ---------------------------------------------------------------------- @property diff --git a/pandas/core/internals/construction.py b/pandas/core/internals/construction.py index 910690a986c1c..c437456794f43 100644 --- a/pandas/core/internals/construction.py +++ b/pandas/core/internals/construction.py @@ -1,6 +1,6 @@ """ Functions for preparing various inputs passed to the DataFrame or Series -constructors before passing them to aBlockManager. +constructors before passing them to a BlockManager. """ from collections import OrderedDict @@ -191,9 +191,9 @@ def init_dict(data, index, columns, dtype=None): nan_dtype = object else: nan_dtype = dtype - v = construct_1d_arraylike_from_scalar(np.nan, len(index), - nan_dtype) - arrays.loc[missing] = [v] * missing.sum() + val = construct_1d_arraylike_from_scalar(np.nan, len(index), + nan_dtype) + arrays.loc[missing] = [val] * missing.sum() else: @@ -254,28 +254,28 @@ def _homogenize(data, index, dtype=None): oindex = None homogenized = [] - for v in data: - if isinstance(v, ABCSeries): + for val in data: + if isinstance(val, ABCSeries): if dtype is not None: - v = v.astype(dtype) - if v.index is not index: + val = val.astype(dtype) + if val.index is not index: # Forces alignment. No need to copy data since we # are putting it into an ndarray later - v = v.reindex(index, copy=False) + val = val.reindex(index, copy=False) else: - if isinstance(v, dict): + if isinstance(val, dict): if oindex is None: oindex = index.astype('O') if isinstance(index, (ABCDatetimeIndex, ABCTimedeltaIndex)): - v = com.dict_compat(v) + val = com.dict_compat(val) else: - v = dict(v) - v = lib.fast_multiget(v, oindex.values, default=np.nan) - v = sanitize_array(v, index, dtype=dtype, copy=False, - raise_cast_failure=False) + val = dict(val) + val = lib.fast_multiget(val, oindex.values, default=np.nan) + val = sanitize_array(val, index, dtype=dtype, copy=False, + raise_cast_failure=False) - homogenized.append(v) + homogenized.append(val) return homogenized @@ -292,16 +292,16 @@ def extract_index(data): have_series = False have_dicts = False - for v in data: - if isinstance(v, ABCSeries): + for val in data: + if isinstance(val, ABCSeries): have_series = True - indexes.append(v.index) - elif isinstance(v, dict): + indexes.append(val.index) + elif isinstance(val, dict): have_dicts = True - indexes.append(list(v.keys())) - elif is_list_like(v) and getattr(v, 'ndim', 1) == 1: + indexes.append(list(val.keys())) + elif is_list_like(val) and getattr(val, 'ndim', 1) == 1: have_raw_arrays = True - raw_lengths.append(len(v)) + raw_lengths.append(len(val)) if not indexes and not raw_lengths: raise ValueError('If using all scalar values, you must pass' @@ -321,8 +321,9 @@ def extract_index(data): if have_series: if lengths[0] != len(index): - msg = ('array length %d does not match index length %d' % - (lengths[0], len(index))) + msg = ('array length {length} does not match index ' + 'length {idx_len}' + .format(length=lengths[0], idx_len=len(index))) raise ValueError(msg) else: index = ibase.default_index(lengths[0]) @@ -352,7 +353,7 @@ def get_names_from_index(data): if n is not None: index[i] = n else: - index[i] = 'Unnamed %d' % count + index[i] = 'Unnamed {count}'.format(count=count) count += 1 return index @@ -514,7 +515,7 @@ def sanitize_index(data, index, copy=False): return data if len(data) != len(index): - raise ValueError('Length of values does not match length of ' 'index') + raise ValueError('Length of values does not match length of index') if isinstance(data, ABCIndexClass) and not copy: pass