Skip to content

Commit 22002e6

Browse files
committed
Operate on categories
1 parent ad9fe5d commit 22002e6

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

doc/source/whatsnew/v1.0.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ Categorical
110110
^^^^^^^^^^^
111111

112112
- Added test to assert the :func:`fillna` raises the correct ValueError message when the value isn't a value from categories (:issue:`13628`)
113-
-
113+
- Using date accessors on a categorical dtyped series of datetimes was incorrectly operating only on the unique categories (:issue: `27952`)
114114
-
115115

116116

pandas/core/indexes/accessors.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from pandas.core.dtypes.generic import ABCSeries
1717

1818
from pandas.core.accessor import PandasDelegate, delegate_names
19-
from pandas.core.algorithms import take_1d
2019
from pandas.core.arrays import DatetimeArray, PeriodArray, TimedeltaArray
2120
from pandas.core.base import NoNewAttributesMixin, PandasObject
2221
from pandas.core.indexes.datetimes import DatetimeIndex
@@ -75,9 +74,7 @@ def _delegate_property_get(self, name):
7574

7675
result = np.asarray(result)
7776

78-
# blow up if we operate on categories
7977
if self.orig is not None:
80-
result = take_1d(result, self.orig.cat.codes)
8178
index = self.orig.index
8279
else:
8380
index = self._parent.index
@@ -324,7 +321,11 @@ def __new__(cls, data):
324321

325322
orig = data if is_categorical_dtype(data) else None
326323
if orig is not None:
327-
data = Series(orig.values.categories, name=orig.name, copy=False)
324+
data = Series(
325+
orig.values.astype(orig.values.categories.dtype),
326+
name=orig.name,
327+
copy=False,
328+
)
328329

329330
if is_datetime64_dtype(data.dtype):
330331
return DatetimeProperties(data, orig)

pandas/tests/indexes/test_category.py

+23
Original file line numberDiff line numberDiff line change
@@ -1123,3 +1123,26 @@ def test_engine_type(self, dtype, engine_type):
11231123
ci.values._codes = ci.values._codes.astype("int64")
11241124
assert np.issubdtype(ci.codes.dtype, dtype)
11251125
assert isinstance(ci._engine, engine_type)
1126+
1127+
def test_dt_tz_localize(self, tz_aware_fixture):
1128+
# GH 27952
1129+
tz = tz_aware_fixture
1130+
datetimes = pd.Series(
1131+
["2019-01-01", "2019-01-01", "2019-01-02"], dtype="datetime64[ns]"
1132+
)
1133+
categorical = datetimes.astype("category")
1134+
result = categorical.dt.tz_localize(tz)
1135+
expected = datetimes.dt.tz_localize(tz)
1136+
tm.assert_series_equal(result, expected)
1137+
1138+
@pytest.mark.parametrize("accessor", [("year"), ("month"), ("day")])
1139+
def test_dt_other_accessors(self, accessor):
1140+
# GH 27952
1141+
tz = None
1142+
datetimes = pd.Series(
1143+
["2018-01-01", "2018-01-01", "2019-01-02"], dtype="datetime64[ns]"
1144+
)
1145+
categorical = datetimes.astype("category")
1146+
result = getattr(categorical.dt, accessor)
1147+
expected = getattr(datetimes.dt, accessor)
1148+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)