Skip to content

Commit acf06ad

Browse files
reidy-preidy-p
authored and
reidy-p
committed
BUG: Maintain column order with groupby.nth
1 parent a277e4a commit acf06ad

File tree

4 files changed

+41
-9
lines changed

4 files changed

+41
-9
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,8 @@ Groupby/Resample/Rolling
793793
- Bug in :meth:`Resampler.asfreq` when frequency of ``TimedeltaIndex`` is a subperiod of a new frequency (:issue:`13022`).
794794
- Bug in :meth:`SeriesGroupBy.mean` when values were integral but could not fit inside of int64, overflowing instead. (:issue:`22487`)
795795
- :func:`RollingGroupby.agg` and :func:`ExpandingGroupby.agg` now support multiple aggregation functions as parameters (:issue:`15072`)
796-
796+
- Bug in :func:`pandas.core.groupby.GroupBy.nth` where column order was not always preserved (:issue:`20760`)
797+
797798
Sparse
798799
^^^^^^
799800

Diff for: pandas/core/groupby/groupby.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ def _set_group_selection(self):
497497

498498
if len(groupers):
499499
# GH12839 clear selected obj cache when group selection changes
500-
self._group_selection = ax.difference(Index(groupers)).tolist()
500+
self._group_selection = ax.difference(Index(groupers),
501+
sort=False).tolist()
501502
self._reset_cache('_selected_obj')
502503

503504
def _set_result_index_ordered(self, result):

Diff for: pandas/core/indexes/base.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -2915,17 +2915,20 @@ def intersection(self, other):
29152915
taken.name = None
29162916
return taken
29172917

2918-
def difference(self, other):
2918+
def difference(self, other, sort=True):
29192919
"""
29202920
Return a new Index with elements from the index that are not in
29212921
`other`.
29222922
29232923
This is the set difference of two Index objects.
2924-
It's sorted if sorting is possible.
29252924
29262925
Parameters
29272926
----------
29282927
other : Index or array-like
2928+
sort : bool, default True
2929+
Sort the resulting index if possible
2930+
2931+
.. versionadded:: 0.24.0
29292932
29302933
Returns
29312934
-------
@@ -2934,10 +2937,12 @@ def difference(self, other):
29342937
Examples
29352938
--------
29362939
2937-
>>> idx1 = pd.Index([1, 2, 3, 4])
2940+
>>> idx1 = pd.Index([2, 1, 3, 4])
29382941
>>> idx2 = pd.Index([3, 4, 5, 6])
29392942
>>> idx1.difference(idx2)
29402943
Int64Index([1, 2], dtype='int64')
2944+
>>> idx1.difference(idx2, sort=False)
2945+
Int64Index([2, 1], dtype='int64')
29412946
29422947
"""
29432948
self._assert_can_do_setop(other)
@@ -2955,10 +2960,11 @@ def difference(self, other):
29552960
label_diff = np.setdiff1d(np.arange(this.size), indexer,
29562961
assume_unique=True)
29572962
the_diff = this.values.take(label_diff)
2958-
try:
2959-
the_diff = sorting.safe_sort(the_diff)
2960-
except TypeError:
2961-
pass
2963+
if sort:
2964+
try:
2965+
the_diff = sorting.safe_sort(the_diff)
2966+
except TypeError:
2967+
pass
29622968

29632969
return this._shallow_copy(the_diff, name=result_name, freq=None)
29642970

Diff for: pandas/tests/groupby/test_nth.py

+24
Original file line numberDiff line numberDiff line change
@@ -390,3 +390,27 @@ def test_nth_empty():
390390
names=['a', 'b']),
391391
columns=['c'])
392392
assert_frame_equal(result, expected)
393+
394+
395+
def test_nth_column_order():
396+
# GH 20760
397+
# Check that nth preserves column order
398+
df = DataFrame([[1, 'b', 100],
399+
[1, 'a', 50],
400+
[1, 'a', np.nan],
401+
[2, 'c', 200],
402+
[2, 'd', 150]],
403+
columns=['A', 'C', 'B'])
404+
result = df.groupby('A').nth(0)
405+
expected = DataFrame([['b', 100.0],
406+
['c', 200.0]],
407+
columns=['C', 'B'],
408+
index=Index([1, 2], name='A'))
409+
assert_frame_equal(result, expected)
410+
411+
result = df.groupby('A').nth(-1, dropna='any')
412+
expected = DataFrame([['a', 50.0],
413+
['d', 150.0]],
414+
columns=['C', 'B'],
415+
index=Index([1, 2], name='A'))
416+
assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)