From 7087b4d926c76d204feb48203364d35c65e4f663 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 18 Dec 2020 15:16:07 -0800 Subject: [PATCH] REF: handle non-list_like cases upfront in sanitize_array (#38563) --- pandas/core/construction.py | 56 ++++++++++++++++++++++--------------- pandas/core/dtypes/cast.py | 5 +++- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/pandas/core/construction.py b/pandas/core/construction.py index 248963ca3c8592..3dc7acc6cf0b5d 100644 --- a/pandas/core/construction.py +++ b/pandas/core/construction.py @@ -449,6 +449,11 @@ def sanitize_array( # extract ndarray or ExtensionArray, ensure we have no PandasArray data = extract_array(data, extract_numpy=True) + if isinstance(data, np.ndarray) and data.ndim == 0: + if dtype is None: + dtype = data.dtype + data = lib.item_from_zerodim(data) + # GH#846 if isinstance(data, np.ndarray): @@ -462,7 +467,7 @@ def sanitize_array( else: subarr = np.array(data, copy=False) else: - # we will try to copy be-definition here + # we will try to copy by-definition here subarr = _try_cast(data, dtype, copy, raise_cast_failure) elif isinstance(data, ABCExtensionArray): @@ -491,30 +496,16 @@ def sanitize_array( # GH#16804 arr = np.arange(data.start, data.stop, data.step, dtype="int64") subarr = _try_cast(arr, dtype, copy, raise_cast_failure) - elif lib.is_scalar(data) and index is not None and dtype is not None: + + elif not is_list_like(data): + if index is None: + raise ValueError("index must be specified when data is not list-like") subarr = construct_1d_arraylike_from_scalar(data, len(index), dtype) + 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: - subarr = construct_1d_arraylike_from_scalar(data, len(index), dtype) - - else: - return subarr.item() - - # the result that we want - elif subarr.ndim == 1: - subarr = _maybe_repeat(subarr, index) - - elif subarr.ndim > 1: - if isinstance(data, np.ndarray): - raise ValueError("Data must be 1-dimensional") - else: - subarr = com.asarray_tuplesafe(data, dtype=dtype) + subarr = _sanitize_ndim(subarr, data, dtype, index) if not (is_extension_array_dtype(subarr.dtype) or is_extension_array_dtype(dtype)): subarr = _sanitize_str_dtypes(subarr, data, dtype, copy) @@ -528,6 +519,27 @@ def sanitize_array( return subarr +def _sanitize_ndim( + result: ArrayLike, data, dtype: Optional[DtypeObj], index: Optional[Index] +) -> ArrayLike: + """ + Ensure we have a 1-dimensional result array. + """ + if getattr(result, "ndim", 0) == 0: + raise ValueError("result should be arraylike with ndim > 0") + + elif result.ndim == 1: + # the result that we want + result = _maybe_repeat(result, index) + + elif result.ndim > 1: + if isinstance(data, np.ndarray): + raise ValueError("Data must be 1-dimensional") + else: + result = com.asarray_tuplesafe(data, dtype=dtype) + return result + + def _sanitize_str_dtypes( result: np.ndarray, data, dtype: Optional[DtypeObj], copy: bool ) -> np.ndarray: @@ -565,7 +577,7 @@ def _try_cast(arr, dtype: Optional[DtypeObj], copy: bool, raise_cast_failure: bo Parameters ---------- - arr : ndarray, scalar, list, tuple, iterator (catchall) + arr : ndarray, list, tuple, iterator (catchall) Excludes: ExtensionArray, Series, Index. dtype : np.dtype, ExtensionDtype or None copy : bool diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index abcc60a15c6411..034fd927a8017d 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -1543,7 +1543,10 @@ def construct_1d_arraylike_from_scalar( """ if dtype is None: - dtype, value = infer_dtype_from_scalar(value, pandas_dtype=True) + try: + dtype, value = infer_dtype_from_scalar(value, pandas_dtype=True) + except OutOfBoundsDatetime: + dtype = np.dtype(object) if is_extension_array_dtype(dtype): cls = dtype.construct_array_type()