From d28921ed8273f9b64e15ee47e282ea873b5a8877 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sun, 21 Jul 2019 13:59:41 -0700 Subject: [PATCH 1/2] BUG: Retain tz transformation in groupby.transform --- doc/source/whatsnew/v0.25.1.rst | 2 +- pandas/core/groupby/generic.py | 4 ++-- pandas/tests/groupby/test_transform.py | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v0.25.1.rst b/doc/source/whatsnew/v0.25.1.rst index 6234bc0f7bd35..69f82f7f85040 100644 --- a/doc/source/whatsnew/v0.25.1.rst +++ b/doc/source/whatsnew/v0.25.1.rst @@ -120,7 +120,7 @@ Plotting Groupby/resample/rolling ^^^^^^^^^^^^^^^^^^^^^^^^ -- +- Bug in :meth:`pandas.core.groupby.DataFrameGroupBy.transform` where applying a timezone conversion lambda function would drop timezone information (:issue:`27496`) - - diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index 7fd0ca94e7997..af980fc95e52e 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -1025,8 +1025,8 @@ def transform(self, func, *args, **kwargs): object.__setattr__(group, "name", name) res = wrapper(group) - if hasattr(res, "values"): - res = res.values + if hasattr(res, "_values"): + res = res._values indexer = self._get_index(name) s = klass(res, indexer) diff --git a/pandas/tests/groupby/test_transform.py b/pandas/tests/groupby/test_transform.py index 1eab3ba253f4d..9a8b7cf18f2c0 100644 --- a/pandas/tests/groupby/test_transform.py +++ b/pandas/tests/groupby/test_transform.py @@ -1001,3 +1001,27 @@ def test_ffill_not_in_axis(func, key, val): expected = df assert_frame_equal(result, expected) + + +def test_transform_lambda_with_datetimetz(): + # GH 27496 + df = DataFrame( + { + "time": [ + Timestamp("2010-07-15 03:14:45"), + Timestamp("2010-11-19 18:47:06"), + ], + "timezone": ["Etc/GMT+4", "US/Eastern"], + } + ) + result = df.groupby(["timezone"])["time"].transform( + lambda x: x.dt.tz_localize(x.name) + ) + expected = Series( + [ + Timestamp("2010-07-15 03:14:45", tz="Etc/GMT+4"), + Timestamp("2010-11-19 18:47:06", tz="US/Eastern"), + ], + name="time", + ) + assert_series_equal(result, expected) From f3cf738b05cc3b48932ef259fa8a682a5de3348d Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sun, 21 Jul 2019 18:04:16 -0700 Subject: [PATCH 2/2] Use isinstance check instead --- pandas/core/groupby/generic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index af980fc95e52e..5b9cec6903749 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -42,7 +42,7 @@ from pandas.core.base import DataError, SpecificationError import pandas.core.common as com from pandas.core.frame import DataFrame -from pandas.core.generic import NDFrame, _shared_docs +from pandas.core.generic import ABCDataFrame, ABCSeries, NDFrame, _shared_docs from pandas.core.groupby import base from pandas.core.groupby.groupby import GroupBy, _apply_docs, _transform_template from pandas.core.index import Index, MultiIndex @@ -1025,7 +1025,7 @@ def transform(self, func, *args, **kwargs): object.__setattr__(group, "name", name) res = wrapper(group) - if hasattr(res, "_values"): + if isinstance(res, (ABCDataFrame, ABCSeries)): res = res._values indexer = self._get_index(name)