diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 5c2d099ed3119..febfa59b7e962 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -370,6 +370,7 @@ MultiIndex ^^^^^^^^^^ - Bug in :meth:`DataFrame.xs` when used with :class:`IndexSlice` raises ``TypeError`` with message ``"Expected label or tuple of labels"`` (:issue:`35301`) +- Bug in :meth:`DataFrame.reset_index` with ``NaT`` values in index raises ``ValueError`` with message ``"cannot convert float NaN to integer"`` (:issue:`36541`) - I/O diff --git a/pandas/core/dtypes/cast.py b/pandas/core/dtypes/cast.py index 3aa1317f6db6d..48391ab7d9373 100644 --- a/pandas/core/dtypes/cast.py +++ b/pandas/core/dtypes/cast.py @@ -73,7 +73,7 @@ ABCSeries, ) from pandas.core.dtypes.inference import is_list_like -from pandas.core.dtypes.missing import isna, notna +from pandas.core.dtypes.missing import is_valid_nat_for_dtype, isna, notna if TYPE_CHECKING: from pandas import Series @@ -1559,6 +1559,11 @@ def construct_1d_arraylike_from_scalar( dtype = np.dtype("object") if not isna(value): value = ensure_str(value) + elif dtype.kind in ["M", "m"] and is_valid_nat_for_dtype(value, dtype): + # GH36541: can't fill array directly with pd.NaT + # > np.empty(10, dtype="datetime64[64]").fill(pd.NaT) + # ValueError: cannot convert float NaN to integer + value = np.datetime64("NaT") subarr = np.empty(length, dtype=dtype) subarr.fill(value) diff --git a/pandas/tests/series/indexing/test_multiindex.py b/pandas/tests/series/indexing/test_multiindex.py index e98a32d62b767..0420d76b5e8a8 100644 --- a/pandas/tests/series/indexing/test_multiindex.py +++ b/pandas/tests/series/indexing/test_multiindex.py @@ -1,8 +1,10 @@ """ test get/set & misc """ +import pytest import pandas as pd from pandas import MultiIndex, Series +import pandas._testing as tm def test_access_none_value_in_multiindex(): @@ -20,3 +22,30 @@ def test_access_none_value_in_multiindex(): s = Series([1] * len(midx), dtype=object, index=midx) result = s.loc[("Level1", "Level2_a")] assert result == 1 + + +@pytest.mark.parametrize( + "ix_data, exp_data", + [ + ( + [(pd.NaT, 1), (pd.NaT, 2)], + {"a": [pd.NaT, pd.NaT], "b": [1, 2], "x": [11, 12]}, + ), + ( + [(pd.NaT, 1), (pd.Timestamp("2020-01-01"), 2)], + {"a": [pd.NaT, pd.Timestamp("2020-01-01")], "b": [1, 2], "x": [11, 12]}, + ), + ( + [(pd.NaT, 1), (pd.Timedelta(123, "d"), 2)], + {"a": [pd.NaT, pd.Timedelta(123, "d")], "b": [1, 2], "x": [11, 12]}, + ), + ], +) +def test_nat_multi_index(ix_data, exp_data): + # GH36541: that reset_index() does not raise ValueError + ix = pd.MultiIndex.from_tuples(ix_data, names=["a", "b"]) + result = pd.DataFrame({"x": [11, 12]}, index=ix) + result = result.reset_index() + + expected = pd.DataFrame(exp_data) + tm.assert_frame_equal(result, expected)