Skip to content

Commit ed529a1

Browse files
authored
BUG: Index constructor silently ignoring dtype (#40411)
1 parent 6cb661c commit ed529a1

File tree

3 files changed

+6
-58
lines changed

3 files changed

+6
-58
lines changed

doc/source/whatsnew/v1.3.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ Conversion
455455
- Bug in :meth:`Series.view` and :meth:`Index.view` when converting between datetime-like (``datetime64[ns]``, ``datetime64[ns, tz]``, ``timedelta64``, ``period``) dtypes (:issue:`39788`)
456456
- Bug in creating a :class:`DataFrame` from an empty ``np.recarray`` not retaining the original dtypes (:issue:`40121`)
457457
- Bug in :class:`DataFrame` failing to raise ``TypeError`` when constructing from a ``frozenset`` (:issue:`40163`)
458-
-
458+
- Bug in :class:`Index` construction silently ignoring a passed ``dtype`` when the data cannot be cast to that dtype (:issue:`21311`)
459459

460460
Strings
461461
^^^^^^^

pandas/core/indexes/base.py

+5-56
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@
6666
can_hold_element,
6767
find_common_type,
6868
infer_dtype_from,
69-
maybe_cast_to_integer_array,
7069
validate_numeric_casting,
7170
)
7271
from pandas.core.dtypes.common import (
@@ -144,6 +143,7 @@
144143
from pandas.core.construction import (
145144
ensure_wrapped_if_datetimelike,
146145
extract_array,
146+
sanitize_array,
147147
)
148148
from pandas.core.indexers import deprecate_ndim_indexing
149149
from pandas.core.indexes.frozen import FrozenList
@@ -398,18 +398,17 @@ def __new__(
398398
# index-like
399399
elif isinstance(data, (np.ndarray, Index, ABCSeries)):
400400

401+
if isinstance(data, ABCMultiIndex):
402+
data = data._values
403+
401404
if dtype is not None:
402405
# we need to avoid having numpy coerce
403406
# things that look like ints/floats to ints unless
404407
# they are actually ints, e.g. '0' and 0.0
405408
# should not be coerced
406409
# GH 11836
410+
data = sanitize_array(data, None, dtype=dtype, copy=copy)
407411

408-
# error: Argument 1 to "_maybe_cast_with_dtype" has incompatible type
409-
# "Union[ndarray, Index, Series]"; expected "ndarray"
410-
data = _maybe_cast_with_dtype(
411-
data, dtype, copy # type: ignore[arg-type]
412-
)
413412
dtype = data.dtype
414413

415414
if data.dtype.kind in ["i", "u", "f"]:
@@ -6314,56 +6313,6 @@ def maybe_extract_name(name, obj, cls) -> Hashable:
63146313
return name
63156314

63166315

6317-
def _maybe_cast_with_dtype(data: np.ndarray, dtype: np.dtype, copy: bool) -> np.ndarray:
6318-
"""
6319-
If a dtype is passed, cast to the closest matching dtype that is supported
6320-
by Index.
6321-
6322-
Parameters
6323-
----------
6324-
data : np.ndarray
6325-
dtype : np.dtype
6326-
copy : bool
6327-
6328-
Returns
6329-
-------
6330-
np.ndarray
6331-
"""
6332-
# we need to avoid having numpy coerce
6333-
# things that look like ints/floats to ints unless
6334-
# they are actually ints, e.g. '0' and 0.0
6335-
# should not be coerced
6336-
# GH 11836
6337-
if is_integer_dtype(dtype):
6338-
inferred = lib.infer_dtype(data, skipna=False)
6339-
if inferred == "integer":
6340-
data = maybe_cast_to_integer_array(data, dtype, copy=copy)
6341-
elif inferred in ["floating", "mixed-integer-float"]:
6342-
if isna(data).any():
6343-
raise ValueError("cannot convert float NaN to integer")
6344-
6345-
if inferred == "mixed-integer-float":
6346-
data = maybe_cast_to_integer_array(data, dtype)
6347-
6348-
# If we are actually all equal to integers,
6349-
# then coerce to integer.
6350-
try:
6351-
data = _try_convert_to_int_array(data, copy, dtype)
6352-
except ValueError:
6353-
data = np.array(data, dtype=np.float64, copy=copy)
6354-
6355-
elif inferred != "string":
6356-
data = data.astype(dtype)
6357-
elif is_float_dtype(dtype):
6358-
inferred = lib.infer_dtype(data, skipna=False)
6359-
if inferred != "string":
6360-
data = data.astype(dtype)
6361-
else:
6362-
data = np.array(data, dtype=dtype, copy=copy)
6363-
6364-
return data
6365-
6366-
63676316
def _maybe_cast_data_without_dtype(subarr):
63686317
"""
63696318
If we have an arraylike input but no passed dtype, try to infer

pandas/tests/indexes/base_class/test_constructors.py

-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ def test_constructor_wrong_kwargs(self):
3636
with tm.assert_produces_warning(FutureWarning):
3737
Index([], foo="bar")
3838

39-
@pytest.mark.xfail(reason="see GH#21311: Index doesn't enforce dtype argument")
4039
def test_constructor_cast(self):
4140
msg = "could not convert string to float"
4241
with pytest.raises(ValueError, match=msg):

0 commit comments

Comments
 (0)