From 9176e811007e34d409a086a792e925c4aaf5f758 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 14 Nov 2023 08:53:13 -0800 Subject: [PATCH 1/3] BUG: period.astype to non-nano dt64 --- doc/source/whatsnew/v2.2.0.rst | 1 + pandas/core/arrays/period.py | 3 ++- pandas/tests/indexes/period/methods/test_astype.py | 8 +++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 3203dc083faf6..04f960708be48 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -421,6 +421,7 @@ I/O Period ^^^^^^ - Bug in :class:`Period` addition silently wrapping around instead of raising ``OverflowError`` (:issue:`55503`) +- Bug in casting from :class:`PeriodDtype` with ``astype`` to ``datetime64`` or :class:`DatetimeTZDtype` with non-nanosecond unit incorrectly returning with nanosecond unit (:issue:`??`) - Plotting diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index f188b73b4fc64..25659d8738057 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -784,7 +784,8 @@ def astype(self, dtype, copy: bool = True): if lib.is_np_dtype(dtype, "M") or isinstance(dtype, DatetimeTZDtype): # GH#45038 match PeriodIndex behavior. tz = getattr(dtype, "tz", None) - return self.to_timestamp().tz_localize(tz) + unit = dtl.dtype_to_unit(dtype) + return self.to_timestamp().tz_localize(tz).as_unit(unit) return super().astype(dtype, copy=copy) diff --git a/pandas/tests/indexes/period/methods/test_astype.py b/pandas/tests/indexes/period/methods/test_astype.py index 07595b6b8c1dd..72b77dc825fb0 100644 --- a/pandas/tests/indexes/period/methods/test_astype.py +++ b/pandas/tests/indexes/period/methods/test_astype.py @@ -139,10 +139,12 @@ def test_astype_array_fallback(self): expected = np.array([True, True]) tm.assert_numpy_array_equal(result, expected) - def test_period_astype_to_timestamp(self): + def test_period_astype_to_timestamp(self, unit): pi = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M") - exp = DatetimeIndex(["2011-01-01", "2011-02-01", "2011-03-01"], tz="US/Eastern") - res = pi.astype("datetime64[ns, US/Eastern]") + exp = DatetimeIndex( + ["2011-01-01", "2011-02-01", "2011-03-01"], tz="US/Eastern" + ).as_unit(unit) + res = pi.astype(f"datetime64[{unit}, US/Eastern]") tm.assert_index_equal(res, exp) assert res.freq == exp.freq From b7f7fdc9d386739042700d148440b7d405db9590 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 14 Nov 2023 09:03:06 -0800 Subject: [PATCH 2/3] BUG: .asfreq with non-nano --- doc/source/whatsnew/v2.2.0.rst | 1 + pandas/core/resample.py | 6 +++++- pandas/tests/resample/test_datetime_index.py | 7 +++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index 04f960708be48..c9eb375a38d61 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -437,6 +437,7 @@ Groupby/resample/rolling - Bug in :meth:`DataFrame.resample` not respecting ``closed`` and ``label`` arguments for :class:`~pandas.tseries.offsets.BusinessDay` (:issue:`55282`) - Bug in :meth:`DataFrame.resample` where bin edges were not correct for :class:`~pandas.tseries.offsets.BusinessDay` (:issue:`55281`) - Bug in :meth:`DataFrame.resample` where bin edges were not correct for :class:`~pandas.tseries.offsets.MonthBegin` (:issue:`55271`) +- Bug in :meth:`DataFrame.asfreq` and :meth:`Series.asfreq` with a :class:`DatetimeIndex` with non-nanosecond resolution incorrectly converting to nanosecond resolution (:issue:`??`) Reshaping ^^^^^^^^^ diff --git a/pandas/core/resample.py b/pandas/core/resample.py index 0827f9c8da4cc..14cd77ec8559b 100644 --- a/pandas/core/resample.py +++ b/pandas/core/resample.py @@ -2782,7 +2782,11 @@ def asfreq( new_obj.index = _asfreq_compat(obj.index, freq) else: - dti = date_range(obj.index.min(), obj.index.max(), freq=freq) + unit = None + if isinstance(obj.index, DatetimeIndex): + # TODO: should we disallow non-DatetimeIndex? + unit = obj.index.unit + dti = date_range(obj.index.min(), obj.index.max(), freq=freq, unit=unit) dti.name = obj.index.name new_obj = obj.reindex(dti, method=method, fill_value=fill_value) if normalize: diff --git a/pandas/tests/resample/test_datetime_index.py b/pandas/tests/resample/test_datetime_index.py index 21937a35629a0..4e464fca89027 100644 --- a/pandas/tests/resample/test_datetime_index.py +++ b/pandas/tests/resample/test_datetime_index.py @@ -1263,10 +1263,13 @@ def test_resample_not_monotonic(unit): ), ], ) -def test_resample_median_bug_1688(dtype): +def test_resample_median_bug_1688(dtype, unit): + dti = DatetimeIndex( + [datetime(2012, 1, 1, 0, 0, 0), datetime(2012, 1, 1, 0, 5, 0)] + ).as_unit(unit) df = DataFrame( [1, 2], - index=[datetime(2012, 1, 1, 0, 0, 0), datetime(2012, 1, 1, 0, 5, 0)], + index=dti, dtype=dtype, ) From b035475ee834ca603f88354260eb9333913a1278 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 14 Nov 2023 09:04:16 -0800 Subject: [PATCH 3/3] GH ref --- doc/source/whatsnew/v2.2.0.rst | 4 ++-- pandas/tests/indexes/period/methods/test_astype.py | 1 + pandas/tests/resample/test_datetime_index.py | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v2.2.0.rst b/doc/source/whatsnew/v2.2.0.rst index c9eb375a38d61..b78924b39073d 100644 --- a/doc/source/whatsnew/v2.2.0.rst +++ b/doc/source/whatsnew/v2.2.0.rst @@ -421,7 +421,7 @@ I/O Period ^^^^^^ - Bug in :class:`Period` addition silently wrapping around instead of raising ``OverflowError`` (:issue:`55503`) -- Bug in casting from :class:`PeriodDtype` with ``astype`` to ``datetime64`` or :class:`DatetimeTZDtype` with non-nanosecond unit incorrectly returning with nanosecond unit (:issue:`??`) +- Bug in casting from :class:`PeriodDtype` with ``astype`` to ``datetime64`` or :class:`DatetimeTZDtype` with non-nanosecond unit incorrectly returning with nanosecond unit (:issue:`55958`) - Plotting @@ -434,10 +434,10 @@ Groupby/resample/rolling - Bug in :class:`.Rolling` where duplicate datetimelike indexes are treated as consecutive rather than equal with ``closed='left'`` and ``closed='neither'`` (:issue:`20712`) - Bug in :meth:`.DataFrameGroupBy.idxmin`, :meth:`.DataFrameGroupBy.idxmax`, :meth:`.SeriesGroupBy.idxmin`, and :meth:`.SeriesGroupBy.idxmax` would not retain :class:`.Categorical` dtype when the index was a :class:`.CategoricalIndex` that contained NA values (:issue:`54234`) - Bug in :meth:`.DataFrameGroupBy.transform` and :meth:`.SeriesGroupBy.transform` when ``observed=False`` and ``f="idxmin"`` or ``f="idxmax"`` would incorrectly raise on unobserved categories (:issue:`54234`) +- Bug in :meth:`DataFrame.asfreq` and :meth:`Series.asfreq` with a :class:`DatetimeIndex` with non-nanosecond resolution incorrectly converting to nanosecond resolution (:issue:`55958`) - Bug in :meth:`DataFrame.resample` not respecting ``closed`` and ``label`` arguments for :class:`~pandas.tseries.offsets.BusinessDay` (:issue:`55282`) - Bug in :meth:`DataFrame.resample` where bin edges were not correct for :class:`~pandas.tseries.offsets.BusinessDay` (:issue:`55281`) - Bug in :meth:`DataFrame.resample` where bin edges were not correct for :class:`~pandas.tseries.offsets.MonthBegin` (:issue:`55271`) -- Bug in :meth:`DataFrame.asfreq` and :meth:`Series.asfreq` with a :class:`DatetimeIndex` with non-nanosecond resolution incorrectly converting to nanosecond resolution (:issue:`??`) Reshaping ^^^^^^^^^ diff --git a/pandas/tests/indexes/period/methods/test_astype.py b/pandas/tests/indexes/period/methods/test_astype.py index 72b77dc825fb0..ba60ffd1fff4d 100644 --- a/pandas/tests/indexes/period/methods/test_astype.py +++ b/pandas/tests/indexes/period/methods/test_astype.py @@ -140,6 +140,7 @@ def test_astype_array_fallback(self): tm.assert_numpy_array_equal(result, expected) def test_period_astype_to_timestamp(self, unit): + # GH#55958 pi = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M") exp = DatetimeIndex( diff --git a/pandas/tests/resample/test_datetime_index.py b/pandas/tests/resample/test_datetime_index.py index 4e464fca89027..0bda66de6a785 100644 --- a/pandas/tests/resample/test_datetime_index.py +++ b/pandas/tests/resample/test_datetime_index.py @@ -1264,6 +1264,7 @@ def test_resample_not_monotonic(unit): ], ) def test_resample_median_bug_1688(dtype, unit): + # GH#55958 dti = DatetimeIndex( [datetime(2012, 1, 1, 0, 0, 0), datetime(2012, 1, 1, 0, 5, 0)] ).as_unit(unit)