From dc77ed43d2fefe51f249872ed12030f7cb678bca Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 28 Jul 2019 09:15:33 -0700 Subject: [PATCH 1/5] cleanup --- pandas/core/arrays/base.py | 13 +- pandas/core/arrays/interval.py | 5 +- pandas/core/base.py | 4 +- pandas/core/dtypes/cast.py | 152 ++++++++++++++--------- pandas/core/generic.py | 21 ++-- pandas/core/internals/blocks.py | 50 ++++++-- pandas/core/resample.py | 10 +- pandas/core/window.py | 2 + pandas/tests/groupby/test_categorical.py | 2 +- 9 files changed, 149 insertions(+), 110 deletions(-) diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index ee796f9896b52..29b3efd99089e 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -14,14 +14,17 @@ from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError from pandas.util._decorators import Appender, Substitution +from pandas.util._validators import validate_fillna_kwargs -from pandas.core.dtypes.common import is_list_like +from pandas.core.dtypes.common import is_array_like, is_list_like from pandas.core.dtypes.dtypes import ExtensionDtype from pandas.core.dtypes.generic import ABCExtensionArray, ABCIndexClass, ABCSeries from pandas.core.dtypes.missing import isna from pandas._typing import ArrayLike from pandas.core import ops +from pandas.core.algorithms import _factorize_array, unique +from pandas.core.missing import backfill_1d, pad_1d from pandas.core.sorting import nargsort _not_implemented_message = "{} does not implement {}." @@ -484,10 +487,6 @@ def fillna(self, value=None, method=None, limit=None): ------- filled : ExtensionArray with NA/NaN filled """ - from pandas.api.types import is_array_like - from pandas.util._validators import validate_fillna_kwargs - from pandas.core.missing import pad_1d, backfill_1d - value, method = validate_fillna_kwargs(value, method) mask = self.isna() @@ -584,8 +583,6 @@ def unique(self): ------- uniques : ExtensionArray """ - from pandas import unique - uniques = unique(self.astype(object)) return self._from_sequence(uniques, dtype=self.dtype) @@ -700,8 +697,6 @@ def factorize(self, na_sentinel: int = -1) -> Tuple[np.ndarray, ABCExtensionArra # original ExtensionArray. # 2. ExtensionArray.factorize. # Complete control over factorization. - from pandas.core.algorithms import _factorize_array - arr, na_value = self._values_for_factorize() labels, uniques = _factorize_array( diff --git a/pandas/core/arrays/interval.py b/pandas/core/arrays/interval.py index 2a0d2c8770063..e87c472dbe88e 100644 --- a/pandas/core/arrays/interval.py +++ b/pandas/core/arrays/interval.py @@ -33,6 +33,7 @@ ) from pandas.core.dtypes.missing import isna, notna +from pandas.core.algorithms import take, value_counts from pandas.core.arrays.base import ExtensionArray, _extension_array_shared_docs from pandas.core.arrays.categorical import Categorical import pandas.core.common as com @@ -796,8 +797,6 @@ def take(self, indices, allow_fill=False, fill_value=None, axis=None, **kwargs): When `indices` contains negative values other than ``-1`` and `allow_fill` is True. """ - from pandas.core.algorithms import take - nv.validate_take(tuple(), kwargs) fill_left = fill_right = fill_value @@ -843,8 +842,6 @@ def value_counts(self, dropna=True): Series.value_counts """ # TODO: implement this is a non-naive way! - from pandas.core.algorithms import value_counts - return value_counts(np.asarray(self), dropna=dropna) # Formatting diff --git a/pandas/core/base.py b/pandas/core/base.py index 89a3d9cfea5ab..29fd7fe096e02 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -4,7 +4,7 @@ import builtins from collections import OrderedDict import textwrap -from typing import Optional +from typing import Dict, Optional import warnings import numpy as np @@ -37,7 +37,7 @@ from pandas.core.arrays import ExtensionArray import pandas.core.nanops as nanops -_shared_docs = dict() +_shared_docs = dict() # type: Dict[str, str] _indexops_doc_kwargs = dict( klass="IndexOpsMixin", inplace="", diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index fd8536e38eee7..2be910f0d389c 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -95,13 +95,11 @@ def maybe_downcast_to_dtype(result, dtype): """ try to cast to the specified dtype (e.g. convert back to bool/int or could be an astype of float64->float32 """ + do_round = False if is_scalar(result): return result - def trans(x): - return x - if isinstance(dtype, str): if dtype == "infer": inferred_type = lib.infer_dtype(ensure_object(result.ravel()), skipna=False) @@ -118,83 +116,115 @@ def trans(x): elif inferred_type == "floating": dtype = "int64" if issubclass(result.dtype.type, np.number): - - def trans(x): # noqa - return x.round() + do_round = True else: dtype = "object" - if isinstance(dtype, str): dtype = np.dtype(dtype) - try: + converted = maybe_downcast_numeric(result, dtype, do_round) + if converted is not result: + return converted + + # a datetimelike + # GH12821, iNaT is casted to float + if dtype.kind in ["M", "m"] and result.dtype.kind in ["i", "f"]: + try: + result = result.astype(dtype) + except Exception: + if dtype.tz: + # convert to datetime and change timezone + from pandas import to_datetime + + result = to_datetime(result).tz_localize("utc") + result = result.tz_convert(dtype.tz) + + elif dtype.type == Period: + # TODO(DatetimeArray): merge with previous elif + from pandas.core.arrays import PeriodArray + + try: + return PeriodArray(result, freq=dtype.freq) + except TypeError: + # e.g. TypeError: int() argument must be a string, a + # bytes-like object or a number, not 'Period + pass + + return result + + +def maybe_downcast_numeric(result, dtype, do_round: bool = False): + """ + Subset of maybe_downcast_to_dtype restricted to numeric dtypes. + + Parameters + ---------- + result : ndarray or ExtensionArray + dtype : np.dtype or ExtensionDtype + do_round : bool + + Returns + ------- + ndarray or ExtensionArray + """ + if not isinstance(dtype, np.dtype): + # e.g. SparseDtype has no itemsize attr + return result + + if isinstance(result, list): + # reached via groupoby.agg _ohlc; really this should be handled + # earlier + result = np.array(result) + + def trans(x): + if do_round: + return x.round() + return x + if dtype.kind == result.dtype.kind: # don't allow upcasts here (except if empty) - if dtype.kind == result.dtype.kind: - if result.dtype.itemsize <= dtype.itemsize and np.prod(result.shape): - return result + if result.dtype.itemsize <= dtype.itemsize and result.size: + return result - if is_bool_dtype(dtype) or is_integer_dtype(dtype): + if is_bool_dtype(dtype) or is_integer_dtype(dtype): + if not result.size: # if we don't have any elements, just astype it - if not np.prod(result.shape): - return trans(result).astype(dtype) + return trans(result).astype(dtype) - # do a test on the first element, if it fails then we are done - r = result.ravel() - arr = np.array([r[0]]) + # do a test on the first element, if it fails then we are done + r = result.ravel() + arr = np.array([r[0]]) + if isna(arr).any() or not np.allclose(arr, trans(arr).astype(dtype), rtol=0): # if we have any nulls, then we are done - if isna(arr).any() or not np.allclose( - arr, trans(arr).astype(dtype), rtol=0 - ): - return result + return result + elif not isinstance(r[0], (np.integer, np.floating, np.bool, int, float, bool)): # a comparable, e.g. a Decimal may slip in here - elif not isinstance( - r[0], (np.integer, np.floating, np.bool, int, float, bool) - ): - return result + return result - if ( - issubclass(result.dtype.type, (np.object_, np.number)) - and notna(result).all() - ): - new_result = trans(result).astype(dtype) - try: - if np.allclose(new_result, result, rtol=0): - return new_result - except Exception: - - # comparison of an object dtype with a number type could - # hit here - if (new_result == result).all(): - return new_result - elif issubclass(dtype.type, np.floating) and not is_bool_dtype(result.dtype): - return result.astype(dtype) - - # a datetimelike - # GH12821, iNaT is casted to float - elif dtype.kind in ["M", "m"] and result.dtype.kind in ["i", "f"]: + if ( + issubclass(result.dtype.type, (np.object_, np.number)) + and notna(result).all() + ): + new_result = trans(result).astype(dtype) try: - result = result.astype(dtype) + if np.allclose(new_result, result, rtol=0): + return new_result except Exception: - if dtype.tz: - # convert to datetime and change timezone - from pandas import to_datetime - - result = to_datetime(result).tz_localize("utc") - result = result.tz_convert(dtype.tz) - - elif dtype.type == Period: - # TODO(DatetimeArray): merge with previous elif - from pandas.core.arrays import PeriodArray - - return PeriodArray(result, freq=dtype.freq) - - except Exception: - pass + # comparison of an object dtype with a number type could + # hit here + if (new_result == result).all(): + return new_result + + elif ( + issubclass(dtype.type, np.floating) + and not is_bool_dtype(result.dtype) + and not is_string_dtype(result.dtype) + ): + return result.astype(dtype) return result diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 97a0b04146297..eecb3d1bee0ce 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -5,6 +5,7 @@ import json import operator import pickle +import re from textwrap import dedent from typing import Callable, Dict, FrozenSet, List, Optional, Set import warnings @@ -4615,8 +4616,6 @@ def filter(self, items=None, like=None, regex=None, axis=None): one two three rabbit 4 5 6 """ - import re - nkw = com.count_not_none(items, like, regex) if nkw > 1: raise TypeError( @@ -6193,8 +6192,6 @@ def fillna( axis = 0 axis = self._get_axis_number(axis) - from pandas import DataFrame - if value is None: if self._is_mixed_type and axis == 1: @@ -6257,7 +6254,7 @@ def fillna( new_data = self._data.fillna( value=value, limit=limit, inplace=inplace, downcast=downcast ) - elif isinstance(value, DataFrame) and self.ndim == 2: + elif isinstance(value, ABCDataFrame) and self.ndim == 2: new_data = self.where(self.notna(), value) else: raise ValueError("invalid fill value with a %s" % type(value)) @@ -7146,9 +7143,7 @@ def asof(self, where, subset=None): 2018-02-27 09:04:30 40.0 NaN """ if isinstance(where, str): - from pandas import to_datetime - - where = to_datetime(where) + where = Timestamp(where) if not self.index.is_monotonic: raise ValueError("asof requires a sorted index") @@ -8720,12 +8715,10 @@ def align( fill_axis=0, broadcast_axis=None, ): - from pandas import DataFrame, Series - method = missing.clean_fill_method(method) if broadcast_axis == 1 and self.ndim != other.ndim: - if isinstance(self, Series): + if isinstance(self, ABCSeries): # this means other is a DataFrame, and we need to broadcast # self cons = self._constructor_expanddim @@ -8743,7 +8736,7 @@ def align( limit=limit, fill_axis=fill_axis, ) - elif isinstance(other, Series): + elif isinstance(other, ABCSeries): # this means self is a DataFrame, and we need to broadcast # other cons = other._constructor_expanddim @@ -8764,7 +8757,7 @@ def align( if axis is not None: axis = self._get_axis_number(axis) - if isinstance(other, DataFrame): + if isinstance(other, ABCDataFrame): return self._align_frame( other, join=join, @@ -8776,7 +8769,7 @@ def align( limit=limit, fill_axis=fill_axis, ) - elif isinstance(other, Series): + elif isinstance(other, ABCSeries): return self._align_series( other, join=join, diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 4ca867b1088e7..8cb55af4b61f5 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -437,7 +437,7 @@ def f(m, v, i): return self.split_and_operate(mask, f, inplace) - def split_and_operate(self, mask, f, inplace): + def split_and_operate(self, mask, f, inplace: bool): """ split the block per-column, and apply the callable f per-column, return a new block for each. Handle @@ -496,17 +496,17 @@ def make_a_block(nv, ref_loc): return new_blocks - def _maybe_downcast(self, blocks, downcast=None): + def _maybe_downcast(self, blocks: List["Block"], downcast=None) -> List["Block"]: # no need to downcast our float # unless indicated - if downcast is None and self.is_float: - return blocks - elif downcast is None and (self.is_timedelta or self.is_datetime): + assert isinstance(blocks, list), blocks + + if downcast is None and ( + self.is_float or self.is_timedelta or self.is_datetime + ): return blocks - if not isinstance(blocks, list): - blocks = [blocks] return _extend_blocks([b.downcast(downcast) for b in blocks]) def downcast(self, dtypes=None): @@ -1355,7 +1355,15 @@ def shift(self, periods, axis=0, fill_value=None): return [self.make_block(new_values)] - def where(self, other, cond, align=True, errors="raise", try_cast=False, axis=0): + def where( + self, + other, + cond, + align=True, + errors="raise", + try_cast: bool = False, + axis: int = 0, + ) -> List["Block"]: """ evaluate the block; return result block(s) from the result @@ -1454,7 +1462,7 @@ def func(cond, values, other): if try_cast: result = self._try_cast_result(result) - return self.make_block(result) + return [self.make_block(result)] # might need to separate out blocks axis = cond.ndim - 1 @@ -1964,7 +1972,15 @@ def shift( ) ] - def where(self, other, cond, align=True, errors="raise", try_cast=False, axis=0): + def where( + self, + other, + cond, + align=True, + errors="raise", + try_cast: bool = False, + axis: int = 0, + ) -> List["Block"]: if isinstance(other, ABCDataFrame): # ExtensionArrays are 1-D, so if we get here then # `other` should be a DataFrame with a single column. @@ -2009,7 +2025,7 @@ def where(self, other, cond, align=True, errors="raise", try_cast=False, axis=0) np.where(cond, self.values, other), dtype=dtype ) - return self.make_block_same_class(result, placement=self.mgr_locs) + return [self.make_block_same_class(result, placement=self.mgr_locs)] @property def _ftype(self): @@ -2767,7 +2783,7 @@ def f(m, v, i): return blocks - def _maybe_downcast(self, blocks, downcast=None): + def _maybe_downcast(self, blocks: List["Block"], downcast=None) -> List["Block"]: if downcast is not None: return blocks @@ -3102,7 +3118,15 @@ def concat_same_type(self, to_concat, placement=None): values, placement=placement or slice(0, len(values), 1), ndim=self.ndim ) - def where(self, other, cond, align=True, errors="raise", try_cast=False, axis=0): + def where( + self, + other, + cond, + align=True, + errors="raise", + try_cast: bool = False, + axis: int = 0, + ) -> List["Block"]: # TODO(CategoricalBlock.where): # This can all be deleted in favor of ExtensionBlock.where once # we enforce the deprecation. diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 66878c3b1026c..b9ee2001eaaac 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -1630,15 +1630,13 @@ def _get_period_bins(self, ax): def _take_new_index(obj, indexer, new_index, axis=0): - from pandas.core.api import Series, DataFrame - - if isinstance(obj, Series): + if isinstance(obj, ABCSeries): new_values = algos.take_1d(obj.values, indexer) - return Series(new_values, index=new_index, name=obj.name) - elif isinstance(obj, DataFrame): + return obj._constructor(new_values, index=new_index, name=obj.name) + elif isinstance(obj, ABCDataFrame): if axis == 1: raise NotImplementedError("axis 1 is not supported") - return DataFrame( + return obj._constructor( obj._data.reindex_indexer(new_axis=new_index, indexer=indexer, axis=1) ) else: diff --git a/pandas/core/window.py b/pandas/core/window.py index 4721d6cfc6dda..e9e69c6dd8faf 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -255,6 +255,8 @@ def _wrap_result(self, result, block=None, obj=None): # coerce if necessary if block is not None: if is_timedelta64_dtype(block.values.dtype): + # TODO: do we know what result.dtype is at this point? + # i.e. can we just do an astype? from pandas import to_timedelta result = to_timedelta(result.ravel(), unit="ns").values.reshape( diff --git a/pandas/tests/groupby/test_categorical.py b/pandas/tests/groupby/test_categorical.py index 486b3b28b29a3..c2c0af78aa518 100644 --- a/pandas/tests/groupby/test_categorical.py +++ b/pandas/tests/groupby/test_categorical.py @@ -508,7 +508,7 @@ def test_datetime(): desc_result = grouped.describe() idx = cats.codes.argsort() - ord_labels = cats.take_nd(idx) + ord_labels = cats.take(idx) # TODO: deprecate take<->take_nd alias ord_data = data.take(idx) expected = ord_data.groupby(ord_labels, observed=False).describe() assert_frame_equal(desc_result, expected) From 7aa52ef8e90fad7d9d884b4eefe079568062a845 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 28 Jul 2019 16:47:48 -0700 Subject: [PATCH 2/5] cleanup --- pandas/core/missing.py | 8 ++++---- pandas/core/sorting.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/core/missing.py b/pandas/core/missing.py index 8f0abc91f7aef..5edf9504157c7 100644 --- a/pandas/core/missing.py +++ b/pandas/core/missing.py @@ -119,7 +119,7 @@ def clean_interp_method(method, **kwargs): "from_derivatives", ] if method in ("spline", "polynomial") and order is None: - raise ValueError("You must specify the order of the spline or " "polynomial.") + raise ValueError("You must specify the order of the spline or polynomial.") if method not in valid: raise ValueError( "method must be one of {valid}. Got '{method}' " @@ -176,7 +176,7 @@ def interpolate_1d( valid_limit_directions = ["forward", "backward", "both"] limit_direction = limit_direction.lower() if limit_direction not in valid_limit_directions: - msg = "Invalid limit_direction: expecting one of {valid!r}, " "got {invalid!r}." + msg = "Invalid limit_direction: expecting one of {valid!r}, got {invalid!r}." raise ValueError( msg.format(valid=valid_limit_directions, invalid=limit_direction) ) @@ -322,7 +322,7 @@ def _interpolate_scipy_wrapper( alt_methods["pchip"] = interpolate.pchip_interpolate except AttributeError: raise ImportError( - "Your version of Scipy does not support " "PCHIP interpolation." + "Your version of Scipy does not support PCHIP interpolation." ) elif method == "akima": alt_methods["akima"] = _akima_interpolate @@ -470,7 +470,7 @@ def interpolate_2d( ndim = values.ndim if values.ndim == 1: if axis != 0: # pragma: no cover - raise AssertionError("cannot interpolate on a ndim == 1 with " "axis != 0") + raise AssertionError("cannot interpolate on a ndim == 1 with axis != 0") values = values.reshape(tuple((1,) + values.shape)) if fill_value is None: diff --git a/pandas/core/sorting.py b/pandas/core/sorting.py index 46e8e97c7de8a..5db31fe6664ea 100644 --- a/pandas/core/sorting.py +++ b/pandas/core/sorting.py @@ -436,7 +436,7 @@ def safe_sort(values, labels=None, na_sentinel=-1, assume_unique=False, verify=T """ if not is_list_like(values): raise TypeError( - "Only list-like objects are allowed to be passed to" "safe_sort as values" + "Only list-like objects are allowed to be passed to safe_sort as values" ) if not isinstance(values, np.ndarray) and not is_extension_array_dtype(values): From 93159296a5384847597d4d281678a72d9345381f Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 2 Aug 2019 08:27:40 -0700 Subject: [PATCH 3/5] revert unrelated changes --- pandas/core/generic.py | 4 +- pandas/core/internals/blocks.py | 50 ++++++------------------ pandas/core/resample.py | 10 +++-- pandas/core/window.py | 2 - pandas/tests/groupby/test_categorical.py | 2 +- 5 files changed, 23 insertions(+), 45 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 68481fc410c70..821c35e0cce2f 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6190,6 +6190,8 @@ def fillna( axis = 0 axis = self._get_axis_number(axis) + from pandas import DataFrame + if value is None: if self._is_mixed_type and axis == 1: @@ -6252,7 +6254,7 @@ def fillna( new_data = self._data.fillna( value=value, limit=limit, inplace=inplace, downcast=downcast ) - elif isinstance(value, ABCDataFrame) and self.ndim == 2: + elif isinstance(value, DataFrame) and self.ndim == 2: new_data = self.where(self.notna(), value) else: raise ValueError("invalid fill value with a %s" % type(value)) diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index c7cc9c92e7aa7..6d70fcfb62d52 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -437,7 +437,7 @@ def f(m, v, i): return self.split_and_operate(mask, f, inplace) - def split_and_operate(self, mask, f, inplace: bool): + def split_and_operate(self, mask, f, inplace): """ split the block per-column, and apply the callable f per-column, return a new block for each. Handle @@ -496,17 +496,17 @@ def make_a_block(nv, ref_loc): return new_blocks - def _maybe_downcast(self, blocks: List["Block"], downcast=None) -> List["Block"]: + def _maybe_downcast(self, blocks, downcast=None): # no need to downcast our float # unless indicated - assert isinstance(blocks, list), blocks - - if downcast is None and ( - self.is_float or self.is_timedelta or self.is_datetime - ): + if downcast is None and self.is_float: + return blocks + elif downcast is None and (self.is_timedelta or self.is_datetime): return blocks + if not isinstance(blocks, list): + blocks = [blocks] return _extend_blocks([b.downcast(downcast) for b in blocks]) def downcast(self, dtypes=None): @@ -1351,15 +1351,7 @@ def shift(self, periods, axis=0, fill_value=None): return [self.make_block(new_values)] - def where( - self, - other, - cond, - align=True, - errors="raise", - try_cast: bool = False, - axis: int = 0, - ) -> List["Block"]: + def where(self, other, cond, align=True, errors="raise", try_cast=False, axis=0): """ evaluate the block; return result block(s) from the result @@ -1458,7 +1450,7 @@ def func(cond, values, other): if try_cast: result = self._try_cast_result(result) - return [self.make_block(result)] + return self.make_block(result) # might need to separate out blocks axis = cond.ndim - 1 @@ -1954,15 +1946,7 @@ def shift( ) ] - def where( - self, - other, - cond, - align=True, - errors="raise", - try_cast: bool = False, - axis: int = 0, - ) -> List["Block"]: + def where(self, other, cond, align=True, errors="raise", try_cast=False, axis=0): if isinstance(other, ABCDataFrame): # ExtensionArrays are 1-D, so if we get here then # `other` should be a DataFrame with a single column. @@ -2007,7 +1991,7 @@ def where( np.where(cond, self.values, other), dtype=dtype ) - return [self.make_block_same_class(result, placement=self.mgr_locs)] + return self.make_block_same_class(result, placement=self.mgr_locs) @property def _ftype(self): @@ -2759,7 +2743,7 @@ def f(m, v, i): return blocks - def _maybe_downcast(self, blocks: List["Block"], downcast=None) -> List["Block"]: + def _maybe_downcast(self, blocks, downcast=None): if downcast is not None: return blocks @@ -3094,15 +3078,7 @@ def concat_same_type(self, to_concat, placement=None): values, placement=placement or slice(0, len(values), 1), ndim=self.ndim ) - def where( - self, - other, - cond, - align=True, - errors="raise", - try_cast: bool = False, - axis: int = 0, - ) -> List["Block"]: + def where(self, other, cond, align=True, errors="raise", try_cast=False, axis=0): # TODO(CategoricalBlock.where): # This can all be deleted in favor of ExtensionBlock.where once # we enforce the deprecation. diff --git a/pandas/core/resample.py b/pandas/core/resample.py index b9ee2001eaaac..66878c3b1026c 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -1630,13 +1630,15 @@ def _get_period_bins(self, ax): def _take_new_index(obj, indexer, new_index, axis=0): - if isinstance(obj, ABCSeries): + from pandas.core.api import Series, DataFrame + + if isinstance(obj, Series): new_values = algos.take_1d(obj.values, indexer) - return obj._constructor(new_values, index=new_index, name=obj.name) - elif isinstance(obj, ABCDataFrame): + return Series(new_values, index=new_index, name=obj.name) + elif isinstance(obj, DataFrame): if axis == 1: raise NotImplementedError("axis 1 is not supported") - return obj._constructor( + return DataFrame( obj._data.reindex_indexer(new_axis=new_index, indexer=indexer, axis=1) ) else: diff --git a/pandas/core/window.py b/pandas/core/window.py index a7425bc1466c3..4b6a1cf2e9a04 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -265,8 +265,6 @@ def _wrap_result(self, result, block=None, obj=None): # coerce if necessary if block is not None: if is_timedelta64_dtype(block.values.dtype): - # TODO: do we know what result.dtype is at this point? - # i.e. can we just do an astype? from pandas import to_timedelta result = to_timedelta(result.ravel(), unit="ns").values.reshape( diff --git a/pandas/tests/groupby/test_categorical.py b/pandas/tests/groupby/test_categorical.py index c2c0af78aa518..486b3b28b29a3 100644 --- a/pandas/tests/groupby/test_categorical.py +++ b/pandas/tests/groupby/test_categorical.py @@ -508,7 +508,7 @@ def test_datetime(): desc_result = grouped.describe() idx = cats.codes.argsort() - ord_labels = cats.take(idx) # TODO: deprecate take<->take_nd alias + ord_labels = cats.take_nd(idx) ord_data = data.take(idx) expected = ord_data.groupby(ord_labels, observed=False).describe() assert_frame_equal(desc_result, expected) From 92f04fbcb0c2cdd8a361624cb925000b4ffdfebe Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 2 Aug 2019 09:02:16 -0700 Subject: [PATCH 4/5] doctest fixup --- pandas/core/dtypes/cast.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 2be910f0d389c..af64650cf91da 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -46,6 +46,7 @@ ) from .dtypes import DatetimeTZDtype, ExtensionDtype, PeriodDtype from .generic import ( + ABCDataFrame, ABCDatetimeArray, ABCDatetimeIndex, ABCPeriodArray, @@ -99,6 +100,9 @@ def maybe_downcast_to_dtype(result, dtype): if is_scalar(result): return result + elif isinstance(result, ABCDataFrame): + # occurs in pivot_table doctest + return result if isinstance(dtype, str): if dtype == "infer": From 44bf1e464bb8dec082deff3bfa5d2f9e8c88513f Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 2 Aug 2019 09:50:09 -0700 Subject: [PATCH 5/5] == -> is --- pandas/core/dtypes/cast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index af64650cf91da..4bb1deffd9524 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -144,7 +144,7 @@ def maybe_downcast_to_dtype(result, dtype): result = to_datetime(result).tz_localize("utc") result = result.tz_convert(dtype.tz) - elif dtype.type == Period: + elif dtype.type is Period: # TODO(DatetimeArray): merge with previous elif from pandas.core.arrays import PeriodArray