Skip to content

Commit 03be332

Browse files
committed
Merge pull request #10705 from jseabold/index-optional-pivot
ENH: Index optional pivot
2 parents fb2ebb6 + 0786158 commit 03be332

File tree

4 files changed

+54
-4
lines changed

4 files changed

+54
-4
lines changed

doc/source/whatsnew/v0.17.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ Other enhancements
110110

111111
- ``pd.merge`` will now allow duplicate column names if they are not merged upon (:issue:`10639`).
112112

113+
- ``pd.pivot`` will now allow passing index as ``None`` (:issue:`3962`).
114+
113115
.. _whatsnew_0170.api:
114116

115117
.. _whatsnew_0170.api_breaking:

pandas/core/frame.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -3460,8 +3460,9 @@ def pivot(self, index=None, columns=None, values=None):
34603460
34613461
Parameters
34623462
----------
3463-
index : string or object
3464-
Column name to use to make new frame's index
3463+
index : string or object, optional
3464+
Column name to use to make new frame's index. If None, uses
3465+
existing index.
34653466
columns : string or object
34663467
Column name to use to make new frame's columns
34673468
values : string or object, optional

pandas/core/reshape.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,17 @@ def pivot(self, index=None, columns=None, values=None):
319319
See DataFrame.pivot
320320
"""
321321
if values is None:
322-
indexed = self.set_index([index, columns])
322+
cols = [columns] if index is None else [index, columns]
323+
append = index is None
324+
indexed = self.set_index(cols, append=append)
323325
return indexed.unstack(columns)
324326
else:
327+
if index is None:
328+
index = self.index
329+
else:
330+
index = self[index]
325331
indexed = Series(self[values].values,
326-
index=MultiIndex.from_arrays([self[index],
332+
index=MultiIndex.from_arrays([index,
327333
self[columns]]))
328334
return indexed.unstack(columns)
329335

pandas/tests/test_frame.py

+41
Original file line numberDiff line numberDiff line change
@@ -9478,6 +9478,47 @@ def test_pivot_integer_bug(self):
94789478
repr(result)
94799479
self.assert_numpy_array_equal(result.columns, ['A', 'B'])
94809480

9481+
def test_pivot_index_none(self):
9482+
# gh-3962
9483+
data = {
9484+
'index': ['A', 'B', 'C', 'C', 'B', 'A'],
9485+
'columns': ['One', 'One', 'One', 'Two', 'Two', 'Two'],
9486+
'values': [1., 2., 3., 3., 2., 1.]
9487+
}
9488+
9489+
frame = DataFrame(data).set_index('index')
9490+
result = frame.pivot(columns='columns', values='values')
9491+
expected = DataFrame({
9492+
'One': {'A': 1., 'B': 2., 'C': 3.},
9493+
'Two': {'A': 1., 'B': 2., 'C': 3.}
9494+
})
9495+
9496+
expected.index.name, expected.columns.name = 'index', 'columns'
9497+
assert_frame_equal(result, expected)
9498+
9499+
# omit values
9500+
result = frame.pivot(columns='columns')
9501+
9502+
expected.columns = pd.MultiIndex.from_tuples([('values', 'One'),
9503+
('values', 'Two')],
9504+
names=[None, 'columns'])
9505+
expected.index.name = 'index'
9506+
assert_frame_equal(result, expected, check_names=False)
9507+
self.assertEqual(result.index.name, 'index',)
9508+
self.assertEqual(result.columns.names, (None, 'columns'))
9509+
expected.columns = expected.columns.droplevel(0)
9510+
9511+
data = {
9512+
'index': range(7),
9513+
'columns': ['One', 'One', 'One', 'Two', 'Two', 'Two'],
9514+
'values': [1., 2., 3., 3., 2., 1.]
9515+
}
9516+
9517+
result = frame.pivot(columns='columns', values='values')
9518+
9519+
expected.columns.name = 'columns'
9520+
assert_frame_equal(result, expected)
9521+
94819522
def test_reindex(self):
94829523
newFrame = self.frame.reindex(self.ts1.index)
94839524

0 commit comments

Comments
 (0)