Skip to content

Commit 2c45501

Browse files
committed
BUG: pivot_table sometimes returns Series (pandas-dev#4386)
1 parent d7fb5bd commit 2c45501

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

doc/source/whatsnew/v0.19.1.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,5 @@ Bug Fixes
8080

8181

8282
- Bug in ``pd.pivot_table`` may raise ``TypeError`` or ``ValueError`` when ``index`` or ``columns``
83-
is not scalar and ``values`` is not specified (:issue:`14380`)
83+
is not scalar and ``values`` is not specified (:issue:`14380`)
84+
- Bug in ``pd.pivot_table`` where a ``Series`` is return instead of a ``DataFrame`` (:issue:`4386`)

pandas/tests/test_categorical.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -3120,9 +3120,9 @@ def test_pivot_table(self):
31203120
[Categorical(["a", "b", "z"], ordered=True),
31213121
Categorical(["c", "d", "y"], ordered=True)],
31223122
names=['A', 'B'])
3123-
expected = Series([1, 2, np.nan, 3, 4, np.nan, np.nan, np.nan, np.nan],
3124-
index=exp_index, name='values')
3125-
tm.assert_series_equal(result, expected)
3123+
exp_data = [1, 2, np.nan, 3, 4, np.nan, np.nan, np.nan, np.nan]
3124+
expected = DataFrame(exp_data, index=exp_index, columns=['values'])
3125+
tm.assert_frame_equal(result, expected)
31263126

31273127
def test_count(self):
31283128

pandas/tools/pivot.py

+3
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',
170170
if len(index) == 0 and len(columns) > 0:
171171
table = table.T
172172

173+
if isinstance(table, Series):
174+
table = table.to_frame()
175+
173176
return table
174177

175178

pandas/tools/tests/test_pivot.py

+35-2
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ def _check_output(result, values_col, index=['A', 'B'],
350350
# no rows
351351
rtable = self.data.pivot_table(columns=['AA', 'BB'], margins=True,
352352
aggfunc=np.mean)
353-
tm.assertIsInstance(rtable, Series)
353+
tm.assertIsInstance(rtable, DataFrame)
354354

355355
table = self.data.pivot_table(index=['AA', 'BB'], margins=True,
356356
aggfunc='mean')
@@ -485,7 +485,7 @@ def test_margins_no_values_no_cols(self):
485485
# Regression test on pivot table: no values or cols passed.
486486
result = self.data[['A', 'B']].pivot_table(
487487
index=['A', 'B'], aggfunc=len, margins=True)
488-
result_list = result.tolist()
488+
result_list = result.values.flatten().tolist()
489489
self.assertEqual(sum(result_list[:-1]), result_list[-1])
490490

491491
def test_margins_no_values_two_rows(self):
@@ -854,6 +854,39 @@ def test_categorical_margins(self):
854854
table = data.pivot_table('x', 'y', 'z', margins=True)
855855
tm.assert_frame_equal(table, expected)
856856

857+
def test_always_return_dataframe(self):
858+
# GH 4386
859+
df = DataFrame({'col1': [3, 4, 5],
860+
'col2': ['C', 'D', 'E'],
861+
'col3': [1, 3, 9]})
862+
result = df.pivot_table('col1', index=['col3', 'col2'], aggfunc=np.sum)
863+
m = MultiIndex.from_arrays([[1, 3, 9],
864+
['C', 'D', 'E']],
865+
names=['col3', 'col2'])
866+
expected = DataFrame([3, 4, 5],
867+
index=m, columns=['col1'])
868+
869+
tm.assert_frame_equal(result, expected)
870+
871+
result = df.pivot_table(
872+
'col1', index='col3', columns='col2', aggfunc=np.sum
873+
)
874+
expected = DataFrame([[3, np.NaN, np.NaN],
875+
[np.NaN, 4, np.NaN],
876+
[np.NaN, np.NaN, 5]],
877+
index=Index([1, 3, 9], name='col3'),
878+
columns=Index(['C', 'D', 'E'], name='col2'))
879+
880+
tm.assert_frame_equal(result, expected)
881+
882+
result = df.pivot_table('col1', index='col3', aggfunc=[np.sum])
883+
m = MultiIndex.from_arrays([['sum'],
884+
['col1']])
885+
expected = DataFrame([3, 4, 5],
886+
index=Index([1, 3, 9], name='col3'),
887+
columns=m)
888+
tm.assert_frame_equal(result, expected)
889+
857890

858891
class TestCrosstab(tm.TestCase):
859892

0 commit comments

Comments
 (0)