Skip to content

Commit 0032c23

Browse files
committed
preserve kwargs order on assign func for py36plus
1 parent e6d8953 commit 0032c23

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

doc/source/whatsnew/v0.21.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ Other Enhancements
117117
- :func:`MultiIndex.is_monotonic_decreasing` has been implemented. Previously returned ``False`` in all cases. (:issue:`16554`)
118118
- :func:`Categorical.rename_categories` now accepts a dict-like argument as `new_categories` and only updates the categories found in that dict. (:issue:`17336`)
119119
- :func:`read_excel` raises ``ImportError`` with a better message if ``xlrd`` is not installed. (:issue:`17613`)
120+
- :func:`assign` will preserve the original order of **kwargs for Python 3.6+ users
120121

121122

122123
.. _whatsnew_0210.api_breaking:

pandas/core/frame.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -2576,10 +2576,10 @@ def assign(self, **kwargs):
25762576
Notes
25772577
-----
25782578
Since ``kwargs`` is a dictionary, the order of your
2579-
arguments may not be preserved. To make things predicatable,
2580-
the columns are inserted in alphabetical order, at the end of
2581-
your DataFrame. Assigning multiple columns within the same
2582-
``assign`` is possible, but you cannot reference other columns
2579+
arguments may not be preserved if you are using Python 3.5 and earlier.
2580+
To make things predicatable, the columns are inserted in alphabetical
2581+
order, at the end of your DataFrame. Assigning multiple columns within
2582+
the same ``assign`` is possible, but you cannot reference other columns
25832583
created within the same ``assign`` call.
25842584
25852585
Examples
@@ -2620,14 +2620,18 @@ def assign(self, **kwargs):
26202620
data = self.copy()
26212621

26222622
# do all calculations first...
2623-
results = {}
2623+
results = OrderedDict()
26242624
for k, v in kwargs.items():
26252625
results[k] = com._apply_if_callable(v, data)
26262626

2627+
# sort by key for 3.5 and earlier, but preserve order for 3.6 and later
2628+
if sys.version_info <= (3, 5):
2629+
results = sorted(results.items())
2630+
else:
2631+
results = results.items()
26272632
# ... and then assign
2628-
for k, v in sorted(results.items()):
2633+
for k, v in results:
26292634
data[k] = v
2630-
26312635
return data
26322636

26332637
def _sanitize_column(self, key, value, broadcast=True):

pandas/tests/frame/test_mutate_columns.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55
from pandas.compat import range, lrange
66
import numpy as np
7+
import sys
78

89
from pandas import DataFrame, Series, Index, MultiIndex
910

@@ -61,14 +62,23 @@ def test_assign_multiple(self):
6162
[3, 6, 9, 3, 6]], columns=list('ABCDE'))
6263
assert_frame_equal(result, expected)
6364

64-
def test_assign_alphabetical(self):
65+
def test_assign_order(self):
6566
# GH 9818
6667
df = DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])
6768
result = df.assign(D=df.A + df.B, C=df.A - df.B)
68-
expected = DataFrame([[1, 2, -1, 3], [3, 4, -1, 7]],
69-
columns=list('ABCD'))
69+
70+
if sys.version_info <= (3, 5):
71+
expected = DataFrame([[1, 2, -1, 3], [3, 4, -1, 7]],
72+
columns=list('ABCD'))
73+
else:
74+
expected = DataFrame([[1, 2, 3, -1], [3, 4, 7, -1]],
75+
columns=list('ABDC'))
7076
assert_frame_equal(result, expected)
7177
result = df.assign(C=df.A - df.B, D=df.A + df.B)
78+
79+
expected = DataFrame([[1, 2, -1, 3], [3, 4, -1, 7]],
80+
columns=list('ABCD'))
81+
7282
assert_frame_equal(result, expected)
7383

7484
def test_assign_bad(self):

0 commit comments

Comments
 (0)