Skip to content

Commit 0fcfcc2

Browse files
committed
BUG: pivot_table someitmes returns Series (pandas-dev#4386)
BUG: pivot_table sometimes returns Series (pandas-dev#4386) BUG: pivot_table sometimes returns Series (pandas-dev#4386)
1 parent 60a335e commit 0fcfcc2

File tree

4 files changed

+55
-14
lines changed

4 files changed

+55
-14
lines changed

doc/source/whatsnew/v0.19.1.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,5 @@ Bug Fixes
8282

8383

8484
- Bug in ``pd.pivot_table`` may raise ``TypeError`` or ``ValueError`` when ``index`` or ``columns``
85-
is not scalar and ``values`` is not specified (:issue:`14380`)
85+
is not scalar and ``values`` is not specified (:issue:`14380`)
86+
- 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

+5-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',
7878
"""
7979
index = _convert_by(index)
8080
columns = _convert_by(columns)
81-
8281
if isinstance(aggfunc, list):
8382
pieces = []
8483
keys = []
@@ -164,12 +163,16 @@ def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',
164163
margins_name=margins_name)
165164

166165
# discard the top level
167-
if values_passed and not values_multi and not table.empty:
166+
if values_passed and not values_multi and not table.empty and \
167+
(table.columns.nlevels > 1):
168168
table = table[values[0]]
169169

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

+45-8
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,14 @@ 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+
expected = self.data.groupby(['AA','BB']).mean()
354+
expected.loc[('All', ''), :] = self.data[['DD', 'EE', 'FF']].mean()
355+
expected = (expected.stack()
356+
.unstack(['BB', 'AA'])
357+
.stack(['AA', 'BB'])
358+
.to_frame())#this still returns a series
354359

355-
table = self.data.pivot_table(index=['AA', 'BB'], margins=True,
356-
aggfunc='mean')
357-
for item in ['DD', 'EE', 'FF']:
358-
totals = table.loc[('All', ''), item]
359-
self.assertEqual(totals, self.data[item].mean())
360+
tm.assert_frame_equal(expected, rtable)
360361

361362
# issue number #8349: pivot_table with margins and dictionary aggfunc
362363
data = [
@@ -485,8 +486,11 @@ def test_margins_no_values_no_cols(self):
485486
# Regression test on pivot table: no values or cols passed.
486487
result = self.data[['A', 'B']].pivot_table(
487488
index=['A', 'B'], aggfunc=len, margins=True)
488-
result_list = result.tolist()
489-
self.assertEqual(sum(result_list[:-1]), result_list[-1])
489+
expected = self.data[['A', 'B']].groupby(['A', 'B']).apply(len)
490+
expected.loc[('All', '')] = expected.sum()
491+
expected = expected.to_frame()
492+
493+
tm.assert_frame_equal(result, expected) #need to return dataframe
490494

491495
def test_margins_no_values_two_rows(self):
492496
# Regression test on pivot table: no values passed but rows are a
@@ -854,6 +858,39 @@ def test_categorical_margins(self):
854858
table = data.pivot_table('x', 'y', 'z', margins=True)
855859
tm.assert_frame_equal(table, expected)
856860

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

858895
class TestCrosstab(tm.TestCase):
859896

0 commit comments

Comments
 (0)