From 66a4371e1de17f5505014a92bae85baa135e1264 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 10 Oct 2019 07:36:24 -0700 Subject: [PATCH 1/3] CLN: post test cleanup --- pandas/core/dtypes/cast.py | 63 ++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 36 deletions(-) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 1e353c97be754..11c083d185538 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -393,11 +393,10 @@ def maybe_promote(dtype, fill_value=np.nan): elif is_float(fill_value): if issubclass(dtype.type, np.bool_): - dtype = np.object_ + dtype = np.dtype(np.object_) + elif issubclass(dtype.type, np.integer): dtype = np.dtype(np.float64) - if not isna(fill_value): - fill_value = dtype.type(fill_value) elif dtype.kind == "f": if not np.can_cast(fill_value, dtype): @@ -411,14 +410,10 @@ def maybe_promote(dtype, fill_value=np.nan): else: dtype = np.dtype(np.object_) - if dtype.kind == "c" and not np.isnan(fill_value): - fill_value = dtype.type(fill_value) - elif is_bool(fill_value): if not issubclass(dtype.type, np.bool_): - dtype = np.object_ - else: - fill_value = np.bool_(fill_value) + dtype = np.dtype(np.object_) + elif is_integer(fill_value): if issubclass(dtype.type, np.bool_): dtype = np.dtype(np.object_) @@ -474,21 +469,10 @@ def maybe_promote(dtype, fill_value=np.nan): }[mst.itemsize] dtype = np.dtype(ndt) - fill_value = dtype.type(fill_value) - - elif issubclass(dtype.type, np.floating): - # check if we can cast - if _check_lossless_cast(fill_value, dtype): - fill_value = dtype.type(fill_value) - - if dtype.kind in ["c", "f"]: - # e.g. if dtype is complex128 and fill_value is 1, we - # want np.complex128(1) - fill_value = dtype.type(fill_value) - elif is_complex(fill_value): if issubclass(dtype.type, np.bool_): dtype = np.dtype(np.object_) + elif issubclass(dtype.type, (np.integer, np.floating)): c8 = np.dtype(np.complex64) info = np.finfo(dtype) if dtype.kind == "f" else np.iinfo(dtype) @@ -507,10 +491,6 @@ def maybe_promote(dtype, fill_value=np.nan): # e.g. mst is np.complex128 and dtype is np.complex64 dtype = mst - if dtype.kind == "c": - # make sure we have a np.complex and not python complex - fill_value = dtype.type(fill_value) - elif fill_value is None: if is_float_dtype(dtype) or is_complex_dtype(dtype): fill_value = np.nan @@ -520,37 +500,48 @@ def maybe_promote(dtype, fill_value=np.nan): elif is_datetime_or_timedelta_dtype(dtype): fill_value = dtype.type("NaT", "ns") else: - dtype = np.object_ + dtype = np.dtype(np.object_) fill_value = np.nan else: - dtype = np.object_ + dtype = np.dtype(np.object_) # in case we have a string that looked like a number if is_extension_array_dtype(dtype): pass elif issubclass(np.dtype(dtype).type, (bytes, str)): - dtype = np.object_ + dtype = np.dtype(np.object_) + fill_value = _ensure_dtype_type(fill_value, dtype) return dtype, fill_value -def _check_lossless_cast(value, dtype: np.dtype) -> bool: +def _ensure_dtype_type(value, dtype): """ - Check if we can cast the given value to the given dtype _losslesly_. + Ensure that the given value is an instance of the given dtype. + + e.g. if out dtype is np.complex64, we should have an instance of that + as opposed to a python complex object. Parameters ---------- value : object - dtype : np.dtype + dtype : np.dtype or ExtensionDtype Returns ------- - bool + object """ - casted = dtype.type(value) - if casted == value: - return True - return False + + # Start with exceptions in which we do _not_ cast to numpy types + if is_extension_array_dtype(dtype): + return value + if dtype == np.object_: + return value + if isna(value): + # e.g. keep np.nan rather than try to cast to np.float32(np.nan) + return value + + return dtype.type(value) def infer_dtype_from(val, pandas_dtype=False): From b41bbc6b4380512e43ce744bacfbb9ae06212525 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Thu, 10 Oct 2019 08:11:31 -0700 Subject: [PATCH 2/3] standardize usage --- pandas/core/dtypes/cast.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 11c083d185538..6ec6cd2473083 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -399,9 +399,10 @@ def maybe_promote(dtype, fill_value=np.nan): dtype = np.dtype(np.float64) elif dtype.kind == "f": - if not np.can_cast(fill_value, dtype): - # e.g. dtype is float32, need float64 - dtype = np.min_scalar_type(fill_value) + mst = np.min_scalar_type(fill_value) + if mst > dtype: + # e.g. mst is np.float64 and dtype is np.float32 + dtype = mst elif dtype.kind == "c": if not np.can_cast(fill_value, dtype): @@ -417,6 +418,7 @@ def maybe_promote(dtype, fill_value=np.nan): elif is_integer(fill_value): if issubclass(dtype.type, np.bool_): dtype = np.dtype(np.object_) + elif issubclass(dtype.type, np.integer): # upcast to prevent overflow mst = np.min_scalar_type(fill_value) @@ -487,7 +489,7 @@ def maybe_promote(dtype, fill_value=np.nan): elif dtype.kind == "c": mst = np.min_scalar_type(fill_value) - if mst > dtype and mst.kind == "c": + if mst > dtype: # e.g. mst is np.complex128 and dtype is np.complex64 dtype = mst From 734bab201d173e459bcefe60db2ab14e03d06878 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 11 Oct 2019 08:23:11 -0700 Subject: [PATCH 3/3] if-> elif --- pandas/core/dtypes/cast.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 7ffc04026a31b..90c2638be5eec 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -483,9 +483,9 @@ def _ensure_dtype_type(value, dtype): # Start with exceptions in which we do _not_ cast to numpy types if is_extension_array_dtype(dtype): return value - if dtype == np.object_: + elif dtype == np.object_: return value - if isna(value): + elif isna(value): # e.g. keep np.nan rather than try to cast to np.float32(np.nan) return value