diff --git a/doc/source/user_guide/timeseries.rst b/doc/source/user_guide/timeseries.rst index a4e458032b787..5351c3ee6b624 100644 --- a/doc/source/user_guide/timeseries.rst +++ b/doc/source/user_guide/timeseries.rst @@ -793,6 +793,7 @@ You may obtain the year, week and day components of the ISO year from the ISO 86 .. ipython:: python idx = pd.date_range(start='2019-12-29', freq='D', periods=4) + idx.isocalendar() idx.to_series().dt.isocalendar() .. _timeseries.offsets: diff --git a/doc/source/whatsnew/v1.1.0.rst b/doc/source/whatsnew/v1.1.0.rst index c33cd505d0948..8b141965bbfe1 100644 --- a/doc/source/whatsnew/v1.1.0.rst +++ b/doc/source/whatsnew/v1.1.0.rst @@ -209,7 +209,7 @@ Other enhancements - :class:`Series.str` now has a `fullmatch` method that matches a regular expression against the entire string in each row of the series, similar to `re.fullmatch` (:issue:`32806`). - :meth:`DataFrame.sample` will now also allow array-like and BitGenerator objects to be passed to ``random_state`` as seeds (:issue:`32503`) - :meth:`MultiIndex.union` will now raise `RuntimeWarning` if the object inside are unsortable, pass `sort=False` to suppress this warning (:issue:`33015`) -- :class:`Series.dt` and :class:`DatatimeIndex` now have an `isocalendar` method that returns a :class:`DataFrame` with year, week, and day calculated according to the ISO 8601 calendar (:issue:`33206`). +- :class:`Series.dt` and :class:`DatatimeIndex` now have an `isocalendar` method that returns a :class:`DataFrame` with year, week, and day calculated according to the ISO 8601 calendar (:issue:`33206`, :issue:`34392`). - The :meth:`DataFrame.to_feather` method now supports additional keyword arguments (e.g. to set the compression) that are added in pyarrow 0.17 (:issue:`33422`). diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 50d792aeb12f4..894a519cb693e 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -1272,17 +1272,17 @@ def isocalendar(self): -------- >>> idx = pd.date_range(start='2019-12-29', freq='D', periods=4) >>> idx.isocalendar() - year week day - 0 2019 52 7 - 1 2020 1 1 - 2 2020 1 2 - 3 2020 1 3 + year week day + 2019-12-29 2019 52 7 + 2019-12-30 2020 1 1 + 2019-12-31 2020 1 2 + 2020-01-01 2020 1 3 >>> idx.isocalendar().week - 0 52 - 1 1 - 2 1 - 3 1 - Name: week, dtype: UInt32 + 2019-12-29 52 + 2019-12-30 1 + 2019-12-31 1 + 2020-01-01 1 + Freq: D, Name: week, dtype: UInt32 """ from pandas import DataFrame diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 47c50dd2c7b14..9a1e750c5de93 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -66,7 +66,7 @@ def _new_DatetimeIndex(cls, d): @inherit_names( - ["to_period", "to_perioddelta", "to_julian_date", "strftime"] + ["to_period", "to_perioddelta", "to_julian_date", "strftime", "isocalendar"] + DatetimeArray._field_ops + DatetimeArray._datetimelike_methods, DatetimeArray, @@ -90,7 +90,6 @@ def _new_DatetimeIndex(cls, d): "date", "time", "timetz", - "isocalendar", ] + DatetimeArray._bool_ops, DatetimeArray, diff --git a/pandas/core/indexes/extension.py b/pandas/core/indexes/extension.py index badf6502aa723..c9367b7e2ee1d 100644 --- a/pandas/core/indexes/extension.py +++ b/pandas/core/indexes/extension.py @@ -10,7 +10,7 @@ from pandas.util._decorators import cache_readonly, doc from pandas.core.dtypes.common import is_dtype_equal, is_object_dtype -from pandas.core.dtypes.generic import ABCSeries +from pandas.core.dtypes.generic import ABCDataFrame, ABCSeries from pandas.core.arrays import ExtensionArray from pandas.core.indexers import deprecate_ndim_indexing @@ -55,6 +55,8 @@ def fget(self): if wrap: if isinstance(result, type(self._data)): return type(self)._simple_new(result, name=self.name) + elif isinstance(result, ABCDataFrame): + return result.set_index(self) return Index(result, name=self.name) return result @@ -77,6 +79,8 @@ def method(self, *args, **kwargs): if wrap: if isinstance(result, type(self._data)): return type(self)._simple_new(result, name=self.name) + elif isinstance(result, ABCDataFrame): + return result.set_index(self) return Index(result, name=self.name) return result diff --git a/pandas/tests/groupby/transform/test_transform.py b/pandas/tests/groupby/transform/test_transform.py index 7997247ca0307..b3347b3c64e6c 100644 --- a/pandas/tests/groupby/transform/test_transform.py +++ b/pandas/tests/groupby/transform/test_transform.py @@ -1022,7 +1022,7 @@ def test_groupby_transform_with_datetimes(func, values): dates = pd.date_range("1/1/2011", periods=10, freq="D") stocks = pd.DataFrame({"price": np.arange(10.0)}, index=dates) - stocks["week_id"] = dates.isocalendar().set_index(dates).week + stocks["week_id"] = dates.isocalendar().week result = stocks.groupby(stocks["week_id"])["price"].transform(func) diff --git a/pandas/tests/indexes/datetimes/test_misc.py b/pandas/tests/indexes/datetimes/test_misc.py index b9373328eb87f..51841727d510b 100644 --- a/pandas/tests/indexes/datetimes/test_misc.py +++ b/pandas/tests/indexes/datetimes/test_misc.py @@ -404,6 +404,7 @@ def test_isocalendar_returns_correct_values_close_to_new_year_with_tz(): expected_data_frame = pd.DataFrame( [[2013, 52, 7], [2014, 1, 1], [2014, 1, 2]], columns=["year", "week", "day"], + index=dates, dtype="UInt32", ) tm.assert_frame_equal(result, expected_data_frame)