diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 7f07187e34c78..b9f2bf00355f0 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -908,6 +908,7 @@ Indexing - Bug in :meth:`NDFrame.xs`, :meth:`DataFrame.iterrows`, :meth:`DataFrame.loc` and :meth:`DataFrame.iloc` not always propagating metadata (:issue:`28283`) - Bug in :meth:`DataFrame.sum` min_count changes dtype if input contains NaNs (:issue:`46947`) - Bug in :class:`IntervalTree` that lead to an infinite recursion. (:issue:`46658`) +- Bug in :class:`PeriodIndex` raising ``AttributeError`` when indexing on ``NA``, rather than putting ``NaT`` in its place. (:issue:`46673`) - Missing diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx index 3332628627739..9b01bbc433b3b 100644 --- a/pandas/_libs/tslibs/period.pyx +++ b/pandas/_libs/tslibs/period.pyx @@ -43,6 +43,7 @@ from libc.time cimport ( import_datetime() cimport pandas._libs.tslibs.util as util +from pandas._libs.missing cimport C_NA from pandas._libs.tslibs.np_datetime cimport ( NPY_DATETIMEUNIT, NPY_FR_D, @@ -1470,7 +1471,7 @@ cdef inline int64_t _extract_ordinal(object item, str freqstr, freq) except? -1: cdef: int64_t ordinal - if checknull_with_nat(item): + if checknull_with_nat(item) or item is C_NA: ordinal = NPY_NAT elif util.is_integer_object(item): if item == NPY_NAT: diff --git a/pandas/tests/arrays/categorical/test_indexing.py b/pandas/tests/arrays/categorical/test_indexing.py index 73ac51c258a94..940aa5ffff040 100644 --- a/pandas/tests/arrays/categorical/test_indexing.py +++ b/pandas/tests/arrays/categorical/test_indexing.py @@ -1,12 +1,16 @@ +import math + import numpy as np import pytest from pandas import ( + NA, Categorical, CategoricalIndex, Index, Interval, IntervalIndex, + NaT, PeriodIndex, Series, Timedelta, @@ -194,6 +198,17 @@ def test_categories_assignments(self): tm.assert_numpy_array_equal(cat.__array__(), exp) tm.assert_index_equal(cat.categories, Index([1, 2, 3])) + @pytest.mark.parametrize( + "null_val", + [None, np.nan, NaT, NA, math.nan, "NaT", "nat", "NAT", "nan", "NaN", "NAN"], + ) + def test_periodindex_on_null_types(self, null_val): + # GH 46673 + result = PeriodIndex(["2022-04-06", "2022-04-07", null_val], freq="D") + expected = PeriodIndex(["2022-04-06", "2022-04-07", "NaT"], dtype="period[D]") + assert result[2] is NaT + tm.assert_index_equal(result, expected) + @pytest.mark.parametrize("new_categories", [[1, 2, 3, 4], [1, 2]]) def test_categories_assignments_wrong_length_raises(self, new_categories): cat = Categorical(["a", "b", "c", "a"]) diff --git a/pandas/tests/series/methods/test_astype.py b/pandas/tests/series/methods/test_astype.py index 6bdf93c43c986..47d6cad0e1743 100644 --- a/pandas/tests/series/methods/test_astype.py +++ b/pandas/tests/series/methods/test_astype.py @@ -446,7 +446,7 @@ def test_astype_string_to_extension_dtype_roundtrip( self, data, dtype, request, nullable_string_dtype ): if dtype == "boolean" or ( - dtype in ("period[M]", "datetime64[ns]", "timedelta64[ns]") and NaT in data + dtype in ("datetime64[ns]", "timedelta64[ns]") and NaT in data ): mark = pytest.mark.xfail( reason="TODO StringArray.astype() with missing values #GH40566"