Skip to content

Commit 1e4e110

Browse files
arw2019Kevin D Smith
authored and
Kevin D Smith
committed
CLN: move maybe_casted_values from pandas/core/frame.py to pandas/core/dtype/cast.py (pandas-dev#36985)
1 parent c442745 commit 1e4e110

File tree

2 files changed

+68
-47
lines changed

2 files changed

+68
-47
lines changed

pandas/core/dtypes/cast.py

+65-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@
7373
ABCSeries,
7474
)
7575
from pandas.core.dtypes.inference import is_list_like
76-
from pandas.core.dtypes.missing import is_valid_nat_for_dtype, isna, notna
76+
from pandas.core.dtypes.missing import (
77+
is_valid_nat_for_dtype,
78+
isna,
79+
na_value_for_dtype,
80+
notna,
81+
)
7782

7883
if TYPE_CHECKING:
7984
from pandas import Series
@@ -439,6 +444,65 @@ def changeit():
439444
return result, False
440445

441446

447+
def maybe_casted_values(index, codes=None):
448+
"""
449+
Convert an index, given directly or as a pair (level, code), to a 1D array.
450+
451+
Parameters
452+
----------
453+
index : Index
454+
codes : sequence of integers (optional)
455+
456+
Returns
457+
-------
458+
ExtensionArray or ndarray
459+
If codes is `None`, the values of `index`.
460+
If codes is passed, an array obtained by taking from `index` the indices
461+
contained in `codes`.
462+
"""
463+
464+
values = index._values
465+
if not isinstance(index, (ABCPeriodIndex, ABCDatetimeIndex)):
466+
if values.dtype == np.object_:
467+
values = lib.maybe_convert_objects(values)
468+
469+
# if we have the codes, extract the values with a mask
470+
if codes is not None:
471+
mask = codes == -1
472+
473+
# we can have situations where the whole mask is -1,
474+
# meaning there is nothing found in codes, so make all nan's
475+
if mask.size > 0 and mask.all():
476+
dtype = index.dtype
477+
fill_value = na_value_for_dtype(dtype)
478+
values = construct_1d_arraylike_from_scalar(fill_value, len(mask), dtype)
479+
else:
480+
values = values.take(codes)
481+
482+
# TODO(https://github.com/pandas-dev/pandas/issues/24206)
483+
# Push this into maybe_upcast_putmask?
484+
# We can't pass EAs there right now. Looks a bit
485+
# complicated.
486+
# So we unbox the ndarray_values, op, re-box.
487+
values_type = type(values)
488+
values_dtype = values.dtype
489+
490+
from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin
491+
492+
if isinstance(values, DatetimeLikeArrayMixin):
493+
values = values._data # TODO: can we de-kludge yet?
494+
495+
if mask.any():
496+
values, _ = maybe_upcast_putmask(values, mask, np.nan)
497+
498+
if issubclass(values_type, DatetimeLikeArrayMixin):
499+
values = values_type(
500+
values, dtype=values_dtype
501+
) # type: ignore[call-arg]
502+
503+
return values
504+
505+
442506
def maybe_promote(dtype, fill_value=np.nan):
443507
"""
444508
Find the minimal dtype that can hold both the given dtype and fill_value.

pandas/core/frame.py

+3-46
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@
8383
infer_dtype_from_scalar,
8484
invalidate_string_dtypes,
8585
maybe_cast_to_datetime,
86+
maybe_casted_values,
8687
maybe_convert_platform,
8788
maybe_downcast_to_dtype,
8889
maybe_infer_to_datetimelike,
8990
maybe_upcast,
90-
maybe_upcast_putmask,
9191
validate_numeric_casting,
9292
)
9393
from pandas.core.dtypes.common import (
@@ -114,7 +114,7 @@
114114
needs_i8_conversion,
115115
pandas_dtype,
116116
)
117-
from pandas.core.dtypes.missing import isna, na_value_for_dtype, notna
117+
from pandas.core.dtypes.missing import isna, notna
118118

119119
from pandas.core import algorithms, common as com, nanops, ops
120120
from pandas.core.accessor import CachedAccessor
@@ -125,15 +125,12 @@
125125
transform,
126126
)
127127
from pandas.core.arrays import Categorical, ExtensionArray
128-
from pandas.core.arrays.datetimelike import DatetimeLikeArrayMixin as DatetimeLikeArray
129128
from pandas.core.arrays.sparse import SparseFrameAccessor
130129
from pandas.core.construction import extract_array
131130
from pandas.core.generic import NDFrame, _shared_docs
132131
from pandas.core.indexes import base as ibase
133132
from pandas.core.indexes.api import Index, ensure_index, ensure_index_from_sequences
134-
from pandas.core.indexes.datetimes import DatetimeIndex
135133
from pandas.core.indexes.multi import MultiIndex, maybe_droplevels
136-
from pandas.core.indexes.period import PeriodIndex
137134
from pandas.core.indexing import check_bool_indexer, convert_to_index_sliceable
138135
from pandas.core.internals import BlockManager
139136
from pandas.core.internals.construction import (
@@ -4849,46 +4846,6 @@ class max type
48494846
else:
48504847
new_obj = self.copy()
48514848

4852-
def _maybe_casted_values(index, labels=None):
4853-
values = index._values
4854-
if not isinstance(index, (PeriodIndex, DatetimeIndex)):
4855-
if values.dtype == np.object_:
4856-
values = lib.maybe_convert_objects(values)
4857-
4858-
# if we have the labels, extract the values with a mask
4859-
if labels is not None:
4860-
mask = labels == -1
4861-
4862-
# we can have situations where the whole mask is -1,
4863-
# meaning there is nothing found in labels, so make all nan's
4864-
if mask.size > 0 and mask.all():
4865-
dtype = index.dtype
4866-
fill_value = na_value_for_dtype(dtype)
4867-
values = construct_1d_arraylike_from_scalar(
4868-
fill_value, len(mask), dtype
4869-
)
4870-
else:
4871-
values = values.take(labels)
4872-
4873-
# TODO(https://github.com/pandas-dev/pandas/issues/24206)
4874-
# Push this into maybe_upcast_putmask?
4875-
# We can't pass EAs there right now. Looks a bit
4876-
# complicated.
4877-
# So we unbox the ndarray_values, op, re-box.
4878-
values_type = type(values)
4879-
values_dtype = values.dtype
4880-
4881-
if issubclass(values_type, DatetimeLikeArray):
4882-
values = values._data # TODO: can we de-kludge yet?
4883-
4884-
if mask.any():
4885-
values, _ = maybe_upcast_putmask(values, mask, np.nan)
4886-
4887-
if issubclass(values_type, DatetimeLikeArray):
4888-
values = values_type(values, dtype=values_dtype)
4889-
4890-
return values
4891-
48924849
new_index = ibase.default_index(len(new_obj))
48934850
if level is not None:
48944851
if not isinstance(level, (tuple, list)):
@@ -4931,7 +4888,7 @@ def _maybe_casted_values(index, labels=None):
49314888
name_lst += [col_fill] * missing
49324889
name = tuple(name_lst)
49334890
# to ndarray and maybe infer different dtype
4934-
level_values = _maybe_casted_values(lev, lab)
4891+
level_values = maybe_casted_values(lev, lab)
49354892
new_obj.insert(0, name, level_values)
49364893

49374894
new_obj.index = new_index

0 commit comments

Comments
 (0)