Skip to content

Commit 81adbe6

Browse files
bobhaffnerjreback
authored andcommitted
BUG: pivot_table strings as aggfunc (#18810)
1 parent 507157d commit 81adbe6

File tree

3 files changed

+49
-2
lines changed

3 files changed

+49
-2
lines changed

doc/source/whatsnew/v0.23.0.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ Reshaping
344344
- Bug in :func:`DataFrame.stack` which fails trying to sort mixed type levels under Python 3 (:issue:`18310`)
345345
- Fixed construction of a :class:`Series` from a ``dict`` containing ``NaN`` as key (:issue:`18480`)
346346
- Bug in :func:`Series.rank` where ``Series`` containing ``NaT`` modifies the ``Series`` inplace (:issue:`18521`)
347-
-
347+
- Bug in :func:`Dataframe.pivot_table` which fails when the ``aggfunc`` arg is of type string. The behavior is now consistent with other methods like ``agg`` and ``apply`` (:issue:`18713`)
348+
348349

349350
Numeric
350351
^^^^^^^

pandas/core/reshape/pivot.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',
3838
fill_value=fill_value, aggfunc=func,
3939
margins=margins, margins_name=margins_name)
4040
pieces.append(table)
41-
keys.append(func.__name__)
41+
keys.append(getattr(func, '__name__', func))
42+
4243
return concat(pieces, keys=keys, axis=1)
4344

4445
keys = index + columns

pandas/tests/reshape/test_pivot.py

+45
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,51 @@ def test_pivot_margins_name_unicode(self):
11091109
expected = pd.DataFrame(index=index)
11101110
tm.assert_frame_equal(table, expected)
11111111

1112+
def test_pivot_string_as_func(self):
1113+
# GH #18713
1114+
# for correctness purposes
1115+
data = DataFrame({'A': ['foo', 'foo', 'foo', 'foo', 'bar', 'bar',
1116+
'bar', 'bar', 'foo', 'foo', 'foo'],
1117+
'B': ['one', 'one', 'one', 'two', 'one', 'one',
1118+
'one', 'two', 'two', 'two', 'one'],
1119+
'C': range(11)})
1120+
1121+
result = pivot_table(data, index='A', columns='B', aggfunc='sum')
1122+
mi = MultiIndex(levels=[['C'], ['one', 'two']],
1123+
labels=[[0, 0], [0, 1]], names=[None, 'B'])
1124+
expected = DataFrame({('C', 'one'): {'bar': 15, 'foo': 13},
1125+
('C', 'two'): {'bar': 7, 'foo': 20}},
1126+
columns=mi).rename_axis('A')
1127+
tm.assert_frame_equal(result, expected)
1128+
1129+
result = pivot_table(data, index='A', columns='B',
1130+
aggfunc=['sum', 'mean'])
1131+
mi = MultiIndex(levels=[['sum', 'mean'], ['C'], ['one', 'two']],
1132+
labels=[[0, 0, 1, 1], [0, 0, 0, 0], [0, 1, 0, 1]],
1133+
names=[None, None, 'B'])
1134+
expected = DataFrame({('mean', 'C', 'one'): {'bar': 5.0, 'foo': 3.25},
1135+
('mean', 'C', 'two'): {'bar': 7.0,
1136+
'foo': 6.666666666666667},
1137+
('sum', 'C', 'one'): {'bar': 15, 'foo': 13},
1138+
('sum', 'C', 'two'): {'bar': 7, 'foo': 20}},
1139+
columns=mi).rename_axis('A')
1140+
tm.assert_frame_equal(result, expected)
1141+
1142+
@pytest.mark.parametrize('f, f_numpy',
1143+
[('sum', np.sum),
1144+
('mean', np.mean),
1145+
('std', np.std),
1146+
(['sum', 'mean'], [np.sum, np.mean]),
1147+
(['sum', 'std'], [np.sum, np.std]),
1148+
(['std', 'mean'], [np.std, np.mean])])
1149+
def test_pivot_string_func_vs_func(self, f, f_numpy):
1150+
# GH #18713
1151+
# for consistency purposes
1152+
result = pivot_table(self.data, index='A', columns='B', aggfunc=f)
1153+
expected = pivot_table(self.data, index='A', columns='B',
1154+
aggfunc=f_numpy)
1155+
tm.assert_frame_equal(result, expected)
1156+
11121157

11131158
class TestCrosstab(object):
11141159

0 commit comments

Comments
 (0)