Skip to content

Commit aaa1688

Browse files
committed
BUG: pivot_table always returns a DataFrame
Before this commit, if * `values` is not list like * `columns` is `None` * `aggfunc` is not instance of `list` `pivot_table` returns a `Series`. This commit adds checking for `columns.nlevels` is greater than 1 to prevent from casting `table` to a `Series`. This will fix #4386.
1 parent eecfa88 commit aaa1688

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,4 @@ Bug Fixes
321321
- Require at least 0.23 version of cython to avoid problems with character encodings (:issue:`14699`)
322322
- Bug in converting object elements of array-like objects to unsigned 64-bit integers (:issue:`4471`)
323323
- Bug in ``pd.pivot_table()`` where no error was raised when values argument was not in the columns (:issue:`14938`)
324+
- Bug in ``pivot_table`` returns ``Series`` in specific circumstance (:issue:`4386`)

pandas/tools/pivot.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',
174174
margins_name=margins_name)
175175

176176
# discard the top level
177-
if values_passed and not values_multi and not table.empty:
177+
if values_passed and not values_multi and not table.empty and \
178+
(table.columns.nlevels > 1):
178179
table = table[values[0]]
179180

180181
if len(index) == 0 and len(columns) > 0:

pandas/tools/tests/test_pivot.py

+38
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,44 @@ def test_categorical_pivot_index_ordering(self):
906906
columns=expected_columns)
907907
tm.assert_frame_equal(result, expected)
908908

909+
def test_pivot_table_not_series(self):
910+
# GH 4386
911+
# pivot_table always returns a DataFrame
912+
# when values is not list like and columns is None
913+
# and aggfunc is not instance of list
914+
df = DataFrame({'col1': [3, 4, 5],
915+
'col2': ['C', 'D', 'E'],
916+
'col3': [1, 3, 9]})
917+
918+
result = df.pivot_table('col1', index=['col3', 'col2'], aggfunc=np.sum)
919+
m = MultiIndex.from_arrays([[1, 3, 9],
920+
['C', 'D', 'E']],
921+
names=['col3', 'col2'])
922+
expected = DataFrame([3, 4, 5],
923+
index=m, columns=['col1'])
924+
925+
tm.assert_frame_equal(result, expected)
926+
927+
result = df.pivot_table(
928+
'col1', index='col3', columns='col2', aggfunc=np.sum
929+
)
930+
expected = DataFrame([[3, np.NaN, np.NaN],
931+
[np.NaN, 4, np.NaN],
932+
[np.NaN, np.NaN, 5]],
933+
index=Index([1, 3, 9], name='col3'),
934+
columns=Index(['C', 'D', 'E'], name='col2'))
935+
936+
tm.assert_frame_equal(result, expected)
937+
938+
result = df.pivot_table('col1', index='col3', aggfunc=[np.sum])
939+
m = MultiIndex.from_arrays([['sum'],
940+
['col1']])
941+
expected = DataFrame([3, 4, 5],
942+
index=Index([1, 3, 9], name='col3'),
943+
columns=m)
944+
945+
tm.assert_frame_equal(result, expected)
946+
909947

910948
class TestCrosstab(tm.TestCase):
911949

0 commit comments

Comments
 (0)