diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index c7230dd7385c2..21d12d02c9008 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -50,6 +50,7 @@ from pandas.core.dtypes.missing import isna, na_value_for_dtype from pandas.core import common as com +from pandas.core.construction import array from pandas.core.indexers import validate_indices _shared_docs = {} # type: Dict[str, str] @@ -1855,8 +1856,6 @@ def searchsorted(arr, value, side="left", sorter=None): and is_integer_dtype(arr) and (is_integer(value) or is_integer_dtype(value)) ): - from .arrays.array_ import array - # if `arr` and `value` have different dtypes, `arr` would be # recast by numpy, causing a slow search. # Before searching below, we therefore try to give `value` the diff --git a/pandas/core/api.py b/pandas/core/api.py index f3ea0976a2869..73323d93b8215 100644 --- a/pandas/core/api.py +++ b/pandas/core/api.py @@ -20,7 +20,8 @@ IntervalDtype, DatetimeTZDtype, ) -from pandas.core.arrays import Categorical, array +from pandas.core.arrays import Categorical +from pandas.core.construction import array from pandas.core.groupby import Grouper, NamedAgg from pandas.io.formats.format import set_eng_float_format from pandas.core.index import ( diff --git a/pandas/core/arrays/__init__.py b/pandas/core/arrays/__init__.py index dab29e9ce71d3..5c83ed8cf5e24 100644 --- a/pandas/core/arrays/__init__.py +++ b/pandas/core/arrays/__init__.py @@ -1,4 +1,3 @@ -from .array_ import array # noqa: F401 from .base import ( # noqa: F401 ExtensionArray, ExtensionOpsMixin, diff --git a/pandas/core/arrays/categorical.py b/pandas/core/arrays/categorical.py index 6200cd14663f8..8b0325748a353 100644 --- a/pandas/core/arrays/categorical.py +++ b/pandas/core/arrays/categorical.py @@ -60,6 +60,7 @@ ) from pandas.core.base import NoNewAttributesMixin, PandasObject, _shared_docs import pandas.core.common as com +from pandas.core.construction import extract_array, sanitize_array from pandas.core.missing import interpolate_2d from pandas.core.sorting import nargsort @@ -374,7 +375,6 @@ def __init__( values = maybe_infer_to_datetimelike(values, convert_dates=True) if not isinstance(values, np.ndarray): values = _convert_to_list_like(values) - from pandas.core.internals.construction import sanitize_array # By convention, empty lists result in object dtype: if len(values) == 0: @@ -2162,8 +2162,6 @@ def __setitem__(self, key, value): If (one or more) Value is not in categories or if a assigned `Categorical` does not have the same categories """ - from pandas.core.internals.arrays import extract_array - value = extract_array(value, extract_numpy=True) # require identical categories set @@ -2526,8 +2524,6 @@ def isin(self, values): >>> s.isin(['lama']) array([ True, False, True, False, True, False]) """ - from pandas.core.internals.construction import sanitize_array - if not is_list_like(values): raise TypeError( "only list-like objects are allowed to be passed" diff --git a/pandas/core/arrays/numpy_.py b/pandas/core/arrays/numpy_.py index 77c9a3bc98690..1c35298fcc6b8 100644 --- a/pandas/core/arrays/numpy_.py +++ b/pandas/core/arrays/numpy_.py @@ -16,6 +16,7 @@ from pandas import compat from pandas.core import nanops from pandas.core.algorithms import searchsorted, take, unique +from pandas.core.construction import extract_array from pandas.core.missing import backfill_1d, pad_1d from .base import ExtensionArray, ExtensionOpsMixin @@ -222,8 +223,6 @@ def __getitem__(self, item): return result def __setitem__(self, key, value): - from pandas.core.internals.arrays import extract_array - value = extract_array(value, extract_numpy=True) if not lib.is_scalar(key) and is_list_like(key): diff --git a/pandas/core/arrays/sparse.py b/pandas/core/arrays/sparse.py index 9376b49112f6f..b8f41b140b245 100644 --- a/pandas/core/arrays/sparse.py +++ b/pandas/core/arrays/sparse.py @@ -52,6 +52,7 @@ from pandas.core.arrays import ExtensionArray, ExtensionOpsMixin from pandas.core.base import PandasObject import pandas.core.common as com +from pandas.core.construction import sanitize_array from pandas.core.missing import interpolate_2d import pandas.core.ops as ops @@ -664,7 +665,6 @@ def __init__( if not is_array_like(data): try: # probably shared code in sanitize_series - from pandas.core.internals.construction import sanitize_array data = sanitize_array(data, index=None) except ValueError: diff --git a/pandas/core/arrays/array_.py b/pandas/core/construction.py similarity index 50% rename from pandas/core/arrays/array_.py rename to pandas/core/construction.py index 314144db57712..9528723a6dc0f 100644 --- a/pandas/core/arrays/array_.py +++ b/pandas/core/construction.py @@ -1,16 +1,51 @@ +""" +Constructor functions intended to be shared by pd.array, Series.__init__, +and Index.__new__. + +These should not depend on core.internals. +""" from typing import Optional, Sequence, Union, cast import numpy as np +import numpy.ma as ma from pandas._libs import lib, tslibs - +from pandas._libs.tslibs import IncompatibleFrequency, OutOfBoundsDatetime + +from pandas.core.dtypes.cast import ( + construct_1d_arraylike_from_scalar, + construct_1d_ndarray_preserving_na, + construct_1d_object_array_from_listlike, + infer_dtype_from_scalar, + maybe_cast_to_datetime, + maybe_cast_to_integer_array, + maybe_castable, + maybe_convert_platform, + maybe_upcast, +) from pandas.core.dtypes.common import ( + is_categorical_dtype, is_datetime64_ns_dtype, is_extension_array_dtype, + is_extension_type, + is_float_dtype, + is_integer_dtype, + is_iterator, + is_list_like, + is_object_dtype, is_timedelta64_ns_dtype, + pandas_dtype, ) from pandas.core.dtypes.dtypes import ExtensionDtype, registry -from pandas.core.dtypes.generic import ABCExtensionArray +from pandas.core.dtypes.generic import ( + ABCExtensionArray, + ABCIndexClass, + ABCPandasArray, + ABCSeries, +) +from pandas.core.dtypes.missing import isna + +import pandas.core.common as com def array( @@ -217,7 +252,6 @@ def array( DatetimeArray, TimedeltaArray, ) - from pandas.core.internals.arrays import extract_array if lib.is_scalar(data): msg = "Cannot pass scalar '{}' to 'pandas.array'." @@ -278,3 +312,241 @@ def array( result = PandasArray._from_sequence(data, dtype=dtype, copy=copy) return result + + +def extract_array(obj, extract_numpy=False): + """ + Extract the ndarray or ExtensionArray from a Series or Index. + + For all other types, `obj` is just returned as is. + + Parameters + ---------- + obj : object + For Series / Index, the underlying ExtensionArray is unboxed. + For Numpy-backed ExtensionArrays, the ndarray is extracted. + + extract_numpy : bool, default False + Whether to extract the ndarray from a PandasArray + + Returns + ------- + arr : object + + Examples + -------- + >>> extract_array(pd.Series(['a', 'b', 'c'], dtype='category')) + [a, b, c] + Categories (3, object): [a, b, c] + + Other objects like lists, arrays, and DataFrames are just passed through. + + >>> extract_array([1, 2, 3]) + [1, 2, 3] + + For an ndarray-backed Series / Index a PandasArray is returned. + + >>> extract_array(pd.Series([1, 2, 3])) + + [1, 2, 3] + Length: 3, dtype: int64 + + To extract all the way down to the ndarray, pass ``extract_numpy=True``. + + >>> extract_array(pd.Series([1, 2, 3]), extract_numpy=True) + array([1, 2, 3]) + """ + if isinstance(obj, (ABCIndexClass, ABCSeries)): + obj = obj.array + + if extract_numpy and isinstance(obj, ABCPandasArray): + obj = obj.to_numpy() + + return obj + + +def sanitize_array(data, index, dtype=None, copy=False, raise_cast_failure=False): + """ + Sanitize input data to an ndarray, copy if specified, coerce to the + dtype if specified. + """ + if dtype is not None: + dtype = pandas_dtype(dtype) + + if isinstance(data, ma.MaskedArray): + mask = ma.getmaskarray(data) + if mask.any(): + data, fill_value = maybe_upcast(data, copy=True) + data.soften_mask() # set hardmask False if it was True + data[mask] = fill_value + else: + data = data.copy() + + # extract ndarray or ExtensionArray, ensure we have no PandasArray + data = extract_array(data, extract_numpy=True) + + # GH#846 + if isinstance(data, np.ndarray): + + if dtype is not None and is_float_dtype(data.dtype) and is_integer_dtype(dtype): + # possibility of nan -> garbage + try: + subarr = _try_cast(data, dtype, copy, True) + except ValueError: + if copy: + subarr = data.copy() + else: + subarr = np.array(data, copy=False) + else: + # we will try to copy be-definition here + subarr = _try_cast(data, dtype, copy, raise_cast_failure) + + elif isinstance(data, ABCExtensionArray): + # it is already ensured above this is not a PandasArray + subarr = data + + if dtype is not None: + subarr = subarr.astype(dtype, copy=copy) + elif copy: + subarr = subarr.copy() + return subarr + + elif isinstance(data, (list, tuple)) and len(data) > 0: + if dtype is not None: + try: + subarr = _try_cast(data, dtype, copy, raise_cast_failure) + except Exception: + if raise_cast_failure: # pragma: no cover + raise + subarr = np.array(data, dtype=object, copy=copy) + subarr = lib.maybe_convert_objects(subarr) + + else: + subarr = maybe_convert_platform(data) + + subarr = maybe_cast_to_datetime(subarr, dtype) + + elif isinstance(data, range): + # GH#16804 + arr = np.arange(data.start, data.stop, data.step, dtype="int64") + subarr = _try_cast(arr, dtype, copy, raise_cast_failure) + else: + subarr = _try_cast(data, dtype, copy, raise_cast_failure) + + # scalar like, GH + if getattr(subarr, "ndim", 0) == 0: + if isinstance(data, list): # pragma: no cover + subarr = np.array(data, dtype=object) + elif index is not None: + value = data + + # figure out the dtype from the value (upcast if necessary) + if dtype is None: + dtype, value = infer_dtype_from_scalar(value) + else: + # need to possibly convert the value here + value = maybe_cast_to_datetime(value, dtype) + + subarr = construct_1d_arraylike_from_scalar(value, len(index), dtype) + + else: + return subarr.item() + + # the result that we want + elif subarr.ndim == 1: + if index is not None: + + # a 1-element ndarray + if len(subarr) != len(index) and len(subarr) == 1: + subarr = construct_1d_arraylike_from_scalar( + subarr[0], len(index), subarr.dtype + ) + + elif subarr.ndim > 1: + if isinstance(data, np.ndarray): + raise Exception("Data must be 1-dimensional") + else: + subarr = com.asarray_tuplesafe(data, dtype=dtype) + + # This is to prevent mixed-type Series getting all casted to + # NumPy string type, e.g. NaN --> '-1#IND'. + if issubclass(subarr.dtype.type, str): + # GH#16605 + # If not empty convert the data to dtype + # GH#19853: If data is a scalar, subarr has already the result + if not lib.is_scalar(data): + if not np.all(isna(data)): + data = np.array(data, dtype=dtype, copy=False) + subarr = np.array(data, dtype=object, copy=copy) + + if ( + not (is_extension_array_dtype(subarr.dtype) or is_extension_array_dtype(dtype)) + and is_object_dtype(subarr.dtype) + and not is_object_dtype(dtype) + ): + inferred = lib.infer_dtype(subarr, skipna=False) + if inferred == "period": + from pandas.core.arrays import period_array + + try: + subarr = period_array(subarr) + except IncompatibleFrequency: + pass + + return subarr + + +def _try_cast(arr, dtype, copy, raise_cast_failure): + """ + Convert input to numpy ndarray and optionally cast to a given dtype. + + Parameters + ---------- + arr : array-like + dtype : np.dtype, ExtensionDtype or None + copy : bool + If False, don't copy the data if not needed. + raise_cast_failure : bool + If True, and if a dtype is specified, raise errors during casting. + Otherwise an object array is returned. + """ + # perf shortcut as this is the most common case + if isinstance(arr, np.ndarray): + if maybe_castable(arr) and not copy and dtype is None: + return arr + + try: + # GH#15832: Check if we are requesting a numeric dype and + # that we can convert the data to the requested dtype. + if is_integer_dtype(dtype): + subarr = maybe_cast_to_integer_array(arr, dtype) + + subarr = maybe_cast_to_datetime(arr, dtype) + # Take care in creating object arrays (but iterators are not + # supported): + if is_object_dtype(dtype) and ( + is_list_like(subarr) + and not (is_iterator(subarr) or isinstance(subarr, np.ndarray)) + ): + subarr = construct_1d_object_array_from_listlike(subarr) + elif not is_extension_type(subarr): + subarr = construct_1d_ndarray_preserving_na(subarr, dtype, copy=copy) + except OutOfBoundsDatetime: + # in case of out of bound datetime64 -> always raise + raise + except (ValueError, TypeError): + if is_categorical_dtype(dtype): + # We *do* allow casting to categorical, since we know + # that Categorical is the only array type for 'category'. + subarr = dtype.construct_array_type()( + arr, dtype.categories, ordered=dtype._ordered + ) + elif is_extension_array_dtype(dtype): + # create an extension array from its dtype + array_type = dtype.construct_array_type()._from_sequence + subarr = array_type(arr, dtype=dtype, copy=copy) + elif dtype is not None and raise_cast_failure: + raise + else: + subarr = np.array(arr, dtype=object, copy=copy) + return subarr diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 9053edf2d1424..42e636ed2204f 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -6,7 +6,7 @@ import operator import pickle from textwrap import dedent -from typing import Callable, FrozenSet, List, Optional, Set +from typing import Callable, Dict, FrozenSet, List, Optional, Set import warnings import weakref @@ -73,7 +73,7 @@ # goal is to be able to define the docs close to function, while still being # able to share -_shared_docs = dict() +_shared_docs = dict() # type: Dict[str, str] _shared_doc_kwargs = dict( axes="keywords for axes", klass="Series/DataFrame", diff --git a/pandas/core/internals/arrays.py b/pandas/core/internals/arrays.py deleted file mode 100644 index 18af328bfa77f..0000000000000 --- a/pandas/core/internals/arrays.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Methods for cleaning, validating, and unboxing arrays. -""" -from pandas.core.dtypes.generic import ABCIndexClass, ABCPandasArray, ABCSeries - - -def extract_array(obj, extract_numpy=False): - """ - Extract the ndarray or ExtensionArray from a Series or Index. - - For all other types, `obj` is just returned as is. - - Parameters - ---------- - obj : object - For Series / Index, the underlying ExtensionArray is unboxed. - For Numpy-backed ExtensionArrays, the ndarray is extracted. - - extract_numpy : bool, default False - Whether to extract the ndarray from a PandasArray - - Returns - ------- - arr : object - - Examples - -------- - >>> extract_array(pd.Series(['a', 'b', 'c'], dtype='category')) - [a, b, c] - Categories (3, object): [a, b, c] - - Other objects like lists, arrays, and DataFrames are just passed through. - - >>> extract_array([1, 2, 3]) - [1, 2, 3] - - For an ndarray-backed Series / Index a PandasArray is returned. - - >>> extract_array(pd.Series([1, 2, 3])) - - [1, 2, 3] - Length: 3, dtype: int64 - - To extract all the way down to the ndarray, pass ``extract_numpy=True``. - - >>> extract_array(pd.Series([1, 2, 3]), extract_numpy=True) - array([1, 2, 3]) - """ - if isinstance(obj, (ABCIndexClass, ABCSeries)): - obj = obj.array - - if extract_numpy and isinstance(obj, ABCPandasArray): - obj = obj.to_numpy() - - return obj diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 549920e230e8a..aa22896783b86 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -77,12 +77,12 @@ ) from pandas.core.base import PandasObject import pandas.core.common as com +from pandas.core.construction import extract_array from pandas.core.indexers import ( check_setitem_lengths, is_empty_indexer, is_scalar_indexer, ) -from pandas.core.internals.arrays import extract_array import pandas.core.missing as missing from pandas.core.nanops import nanpercentile diff --git a/pandas/core/internals/construction.py b/pandas/core/internals/construction.py index c437f686bd17b..74b16f0e72883 100644 --- a/pandas/core/internals/construction.py +++ b/pandas/core/internals/construction.py @@ -8,18 +8,12 @@ import numpy.ma as ma from pandas._libs import lib -from pandas._libs.tslibs import IncompatibleFrequency, OutOfBoundsDatetime import pandas.compat as compat from pandas.compat import PY36, raise_with_traceback from pandas.core.dtypes.cast import ( construct_1d_arraylike_from_scalar, - construct_1d_ndarray_preserving_na, - construct_1d_object_array_from_listlike, - infer_dtype_from_scalar, maybe_cast_to_datetime, - maybe_cast_to_integer_array, - maybe_castable, maybe_convert_platform, maybe_infer_to_datetimelike, maybe_upcast, @@ -29,13 +23,9 @@ is_datetime64tz_dtype, is_dtype_equal, is_extension_array_dtype, - is_extension_type, - is_float_dtype, is_integer_dtype, - is_iterator, is_list_like, is_object_dtype, - pandas_dtype, ) from pandas.core.dtypes.generic import ( ABCDataFrame, @@ -45,10 +35,10 @@ ABCSeries, ABCTimedeltaIndex, ) -from pandas.core.dtypes.missing import isna from pandas.core import algorithms, common as com -from pandas.core.arrays import Categorical, ExtensionArray, period_array +from pandas.core.arrays import Categorical +from pandas.core.construction import sanitize_array from pandas.core.index import ( Index, _get_objs_combined_axis, @@ -60,7 +50,6 @@ create_block_manager_from_arrays, create_block_manager_from_blocks, ) -from pandas.core.internals.arrays import extract_array # --------------------------------------------------------------------- # BlockManager Interface @@ -625,186 +614,3 @@ def sanitize_index(data, index, copy=False): data = sanitize_array(data, index, copy=copy) return data - - -def sanitize_array(data, index, dtype=None, copy=False, raise_cast_failure=False): - """ - Sanitize input data to an ndarray, copy if specified, coerce to the - dtype if specified. - """ - if dtype is not None: - dtype = pandas_dtype(dtype) - - if isinstance(data, ma.MaskedArray): - mask = ma.getmaskarray(data) - if mask.any(): - data, fill_value = maybe_upcast(data, copy=True) - data.soften_mask() # set hardmask False if it was True - data[mask] = fill_value - else: - data = data.copy() - - # extract ndarray or ExtensionArray, ensure we have no PandasArray - data = extract_array(data, extract_numpy=True) - - # GH#846 - if isinstance(data, np.ndarray): - - if dtype is not None and is_float_dtype(data.dtype) and is_integer_dtype(dtype): - # possibility of nan -> garbage - try: - subarr = _try_cast(data, dtype, copy, True) - except ValueError: - if copy: - subarr = data.copy() - else: - subarr = np.array(data, copy=False) - else: - # we will try to copy be-definition here - subarr = _try_cast(data, dtype, copy, raise_cast_failure) - - elif isinstance(data, ExtensionArray): - # it is already ensured above this is not a PandasArray - subarr = data - - if dtype is not None: - subarr = subarr.astype(dtype, copy=copy) - elif copy: - subarr = subarr.copy() - return subarr - - elif isinstance(data, (list, tuple)) and len(data) > 0: - if dtype is not None: - try: - subarr = _try_cast(data, dtype, copy, raise_cast_failure) - except Exception: - if raise_cast_failure: # pragma: no cover - raise - subarr = np.array(data, dtype=object, copy=copy) - subarr = lib.maybe_convert_objects(subarr) - - else: - subarr = maybe_convert_platform(data) - - subarr = maybe_cast_to_datetime(subarr, dtype) - - elif isinstance(data, range): - # GH#16804 - arr = np.arange(data.start, data.stop, data.step, dtype="int64") - subarr = _try_cast(arr, dtype, copy, raise_cast_failure) - else: - subarr = _try_cast(data, dtype, copy, raise_cast_failure) - - # scalar like, GH - if getattr(subarr, "ndim", 0) == 0: - if isinstance(data, list): # pragma: no cover - subarr = np.array(data, dtype=object) - elif index is not None: - value = data - - # figure out the dtype from the value (upcast if necessary) - if dtype is None: - dtype, value = infer_dtype_from_scalar(value) - else: - # need to possibly convert the value here - value = maybe_cast_to_datetime(value, dtype) - - subarr = construct_1d_arraylike_from_scalar(value, len(index), dtype) - - else: - return subarr.item() - - # the result that we want - elif subarr.ndim == 1: - if index is not None: - - # a 1-element ndarray - if len(subarr) != len(index) and len(subarr) == 1: - subarr = construct_1d_arraylike_from_scalar( - subarr[0], len(index), subarr.dtype - ) - - elif subarr.ndim > 1: - if isinstance(data, np.ndarray): - raise Exception("Data must be 1-dimensional") - else: - subarr = com.asarray_tuplesafe(data, dtype=dtype) - - # This is to prevent mixed-type Series getting all casted to - # NumPy string type, e.g. NaN --> '-1#IND'. - if issubclass(subarr.dtype.type, str): - # GH#16605 - # If not empty convert the data to dtype - # GH#19853: If data is a scalar, subarr has already the result - if not lib.is_scalar(data): - if not np.all(isna(data)): - data = np.array(data, dtype=dtype, copy=False) - subarr = np.array(data, dtype=object, copy=copy) - - if ( - not (is_extension_array_dtype(subarr.dtype) or is_extension_array_dtype(dtype)) - and is_object_dtype(subarr.dtype) - and not is_object_dtype(dtype) - ): - inferred = lib.infer_dtype(subarr, skipna=False) - if inferred == "period": - try: - subarr = period_array(subarr) - except IncompatibleFrequency: - pass - - return subarr - - -def _try_cast(arr, dtype, copy, raise_cast_failure): - """ - Convert input to numpy ndarray and optionally cast to a given dtype. - - Parameters - ---------- - arr : array-like - dtype : np.dtype, ExtensionDtype or None - copy : bool - If False, don't copy the data if not needed. - raise_cast_failure : bool - If True, and if a dtype is specified, raise errors during casting. - Otherwise an object array is returned. - """ - # perf shortcut as this is the most common case - if isinstance(arr, np.ndarray): - if maybe_castable(arr) and not copy and dtype is None: - return arr - - try: - # GH#15832: Check if we are requesting a numeric dype and - # that we can convert the data to the requested dtype. - if is_integer_dtype(dtype): - subarr = maybe_cast_to_integer_array(arr, dtype) - - subarr = maybe_cast_to_datetime(arr, dtype) - # Take care in creating object arrays (but iterators are not - # supported): - if is_object_dtype(dtype) and ( - is_list_like(subarr) - and not (is_iterator(subarr) or isinstance(subarr, np.ndarray)) - ): - subarr = construct_1d_object_array_from_listlike(subarr) - elif not is_extension_type(subarr): - subarr = construct_1d_ndarray_preserving_na(subarr, dtype, copy=copy) - except OutOfBoundsDatetime: - # in case of out of bound datetime64 -> always raise - raise - except (ValueError, TypeError): - if is_categorical_dtype(dtype): - # We *do* allow casting to categorical, since we know - # that Categorical is the only array type for 'category'. - subarr = Categorical(arr, dtype.categories, ordered=dtype._ordered) - elif is_extension_array_dtype(dtype): - # create an extension array from its dtype - array_type = dtype.construct_array_type()._from_sequence - subarr = array_type(arr, dtype=dtype, copy=copy) - elif dtype is not None and raise_cast_failure: - raise - else: - subarr = np.array(arr, dtype=object, copy=copy) - return subarr diff --git a/pandas/core/reshape/reshape.py b/pandas/core/reshape/reshape.py index 8d5b521ef7799..1f519d4c0867d 100644 --- a/pandas/core/reshape/reshape.py +++ b/pandas/core/reshape/reshape.py @@ -22,9 +22,9 @@ import pandas.core.algorithms as algos from pandas.core.arrays import SparseArray from pandas.core.arrays.categorical import _factorize_from_iterable +from pandas.core.construction import extract_array from pandas.core.frame import DataFrame from pandas.core.index import Index, MultiIndex -from pandas.core.internals.arrays import extract_array from pandas.core.series import Series from pandas.core.sorting import ( compress_group_index, diff --git a/pandas/core/series.py b/pandas/core/series.py index 418b3fc8c57d0..dcf9dd4def9e5 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -61,6 +61,7 @@ from pandas.core.arrays.categorical import Categorical, CategoricalAccessor from pandas.core.arrays.sparse import SparseAccessor import pandas.core.common as com +from pandas.core.construction import extract_array, sanitize_array from pandas.core.index import ( Float64Index, Index, @@ -76,7 +77,6 @@ from pandas.core.indexes.timedeltas import TimedeltaIndex from pandas.core.indexing import check_bool_indexer from pandas.core.internals import SingleBlockManager -from pandas.core.internals.construction import sanitize_array from pandas.core.strings import StringMethods from pandas.core.tools.datetimes import to_datetime @@ -801,8 +801,6 @@ def __array_ufunc__( self, ufunc: Callable, method: str, *inputs: Any, **kwargs: Any ): # TODO: handle DataFrame - from pandas.core.internals.construction import extract_array - cls = type(self) # for binary ops, use our custom dunder methods diff --git a/pandas/core/sorting.py b/pandas/core/sorting.py index 5f3ed87424d0e..454156fd97344 100644 --- a/pandas/core/sorting.py +++ b/pandas/core/sorting.py @@ -15,6 +15,7 @@ from pandas.core.dtypes.missing import isna import pandas.core.algorithms as algorithms +from pandas.core.construction import extract_array _INT64_MAX = np.iinfo(np.int64).max @@ -240,8 +241,6 @@ def nargsort(items, kind="quicksort", ascending=True, na_position="last"): handles NaNs. It adds ascending and na_position parameters. GH #6399, #5231 """ - from pandas.core.internals.arrays import extract_array - items = extract_array(items) mask = np.asarray(isna(items))