Skip to content

Commit 02ef0a8

Browse files
committed
BUG: pivot_table sometimes returns Series (pandas-dev#4386)
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) pep 8 fixes Restructure condional and update whatsnew
1 parent 2e276fb commit 02ef0a8

File tree

5 files changed

+55
-15
lines changed

5 files changed

+55
-15
lines changed

Diff for: doc/source/whatsnew/v0.19.1.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,4 @@ Bug Fixes
5858
- Bug in ``df.groupby`` causing an ``AttributeError`` when grouping a single index frame by a column and the index level (:issue`14327`)
5959
- Bug in ``df.groupby`` where ``TypeError`` raised when ``pd.Grouper(key=...)`` is passed in a list (:issue:`14334`)
6060
- Bug in ``pd.pivot_table`` may raise ``TypeError`` or ``ValueError`` when ``index`` or ``columns``
61-
is not scalar and ``values`` is not specified (:issue:`14380`)
61+
is not scalar and ``values`` is not specified (:issue:`14380`)

Diff for: doc/source/whatsnew/v0.20.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,4 @@ Performance Improvements
8080

8181
Bug Fixes
8282
~~~~~~~~~
83+
- Bug in ``pd.pivot_table`` where a ``Series`` is return instead of a ``DataFrame`` (:issue:`4386`)

Diff for: 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

Diff for: 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

Diff for: pandas/tools/tests/test_pivot.py

+45-9
Original file line numberDiff line numberDiff line change
@@ -350,13 +350,13 @@ 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)
354-
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())
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())
359+
tm.assert_frame_equal(expected, rtable)
360360

361361
# issue number #8349: pivot_table with margins and dictionary aggfunc
362362
data = [
@@ -485,8 +485,11 @@ 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()
489-
self.assertEqual(sum(result_list[:-1]), result_list[-1])
488+
expected = self.data[['A', 'B']].groupby(['A', 'B']).apply(len)
489+
expected.loc[('All', '')] = expected.sum()
490+
expected = expected.to_frame()
491+
492+
tm.assert_frame_equal(result, expected)
490493

491494
def test_margins_no_values_two_rows(self):
492495
# Regression test on pivot table: no values passed but rows are a
@@ -854,6 +857,39 @@ def test_categorical_margins(self):
854857
table = data.pivot_table('x', 'y', 'z', margins=True)
855858
tm.assert_frame_equal(table, expected)
856859

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

858894
class TestCrosstab(tm.TestCase):
859895

0 commit comments

Comments
 (0)