Skip to content

Commit 84786b9

Browse files
jbrockmendelSeeminSyed
authored andcommitted
BUG: pivot_table losing tz (pandas-dev#32558)
1 parent 6d2445f commit 84786b9

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

doc/source/whatsnew/v1.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ Reshaping
367367
- :meth:`Series.append` will now raise a ``TypeError`` when passed a DataFrame or a sequence containing Dataframe (:issue:`31413`)
368368
- :meth:`DataFrame.replace` and :meth:`Series.replace` will raise a ``TypeError`` if ``to_replace`` is not an expected type. Previously the ``replace`` would fail silently (:issue:`18634`)
369369
- Bug in :meth:`DataFrame.apply` where callback was called with :class:`Series` parameter even though ``raw=True`` requested. (:issue:`32423`)
370+
- Bug in :meth:`DataFrame.pivot_table` losing timezone information when creating a :class:`MultiIndex` level from a column with timezone-aware dtype (:issue:`32558`)
370371

371372

372373
Sparse

pandas/core/indexes/multi.py

+1
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ def from_product(cls, iterables, sortorder=None, names=lib.no_default):
565565
if names is lib.no_default:
566566
names = [getattr(it, "name", None) for it in iterables]
567567

568+
# codes are all ndarrays, so cartesian_product is lossless
568569
codes = cartesian_product(codes)
569570
return MultiIndex(levels, codes, sortorder=sortorder, names=names)
570571

pandas/core/reshape/util.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from pandas.core.dtypes.common import is_list_like
44

5-
import pandas.core.common as com
6-
75

86
def cartesian_product(X):
97
"""
@@ -51,9 +49,20 @@ def cartesian_product(X):
5149
# if any factor is empty, the cartesian product is empty
5250
b = np.zeros_like(cumprodX)
5351

54-
return [
55-
np.tile(
56-
np.repeat(np.asarray(com.values_from_object(x)), b[i]), np.product(a[i])
57-
)
58-
for i, x in enumerate(X)
59-
]
52+
return [_tile_compat(np.repeat(x, b[i]), np.product(a[i])) for i, x in enumerate(X)]
53+
54+
55+
def _tile_compat(arr, num: int):
56+
"""
57+
Index compat for np.tile.
58+
59+
Notes
60+
-----
61+
Does not support multi-dimensional `num`.
62+
"""
63+
if isinstance(arr, np.ndarray):
64+
return np.tile(arr, num)
65+
66+
# Otherwise we have an Index
67+
taker = np.tile(np.arange(len(arr)), num)
68+
return arr.take(taker)

pandas/tests/reshape/test_pivot.py

+8
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,14 @@ def test_pivot_table_multiindex_only(self, cols):
10261026

10271027
tm.assert_frame_equal(result, expected)
10281028

1029+
def test_pivot_table_retains_tz(self):
1030+
dti = date_range("2016-01-01", periods=3, tz="Europe/Amsterdam")
1031+
df = DataFrame({"A": np.random.randn(3), "B": np.random.randn(3), "C": dti})
1032+
result = df.pivot_table(index=["B", "C"], dropna=False)
1033+
1034+
# check tz retention
1035+
assert result.index.levels[1].equals(dti)
1036+
10291037
def test_pivot_integer_columns(self):
10301038
# caused by upstream bug in unstack
10311039

pandas/tests/reshape/test_util.py

+16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ def test_datetimeindex(self):
2525
tm.assert_index_equal(result1, expected1)
2626
tm.assert_index_equal(result2, expected2)
2727

28+
def test_tzaware_retained(self):
29+
x = date_range("2000-01-01", periods=2, tz="US/Pacific")
30+
y = np.array([3, 4])
31+
result1, result2 = cartesian_product([x, y])
32+
33+
expected = x.repeat(2)
34+
tm.assert_index_equal(result1, expected)
35+
36+
def test_tzaware_retained_categorical(self):
37+
x = date_range("2000-01-01", periods=2, tz="US/Pacific").astype("category")
38+
y = np.array([3, 4])
39+
result1, result2 = cartesian_product([x, y])
40+
41+
expected = x.repeat(2)
42+
tm.assert_index_equal(result1, expected)
43+
2844
def test_empty(self):
2945
# product of empty factors
3046
X = [[], [0, 1], []]

0 commit comments

Comments
 (0)