Skip to content

Commit 269a3e4

Browse files
BUG: agg order for list is not maintained (#41017)
1 parent 6f21ec8 commit 269a3e4

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,7 @@ Other
973973
- Bug in :meth:`DataFrame.equals`, :meth:`Series.equals`, :meth:`Index.equals` with object-dtype containing ``np.datetime64("NaT")`` or ``np.timedelta64("NaT")`` (:issue:`39650`)
974974
- Bug in :func:`pandas.util.show_versions` where console JSON output was not proper JSON (:issue:`39701`)
975975
- Bug in :meth:`DataFrame.convert_dtypes` incorrectly raised ValueError when called on an empty DataFrame (:issue:`40393`)
976+
- Bug in :meth:`DataFrame.agg()` not sorting the aggregated axis in the order of the provided aggragation functions when one or more aggregation function fails to produce results (:issue:`33634`)
976977
- Bug in :meth:`DataFrame.clip` not interpreting missing values as no threshold (:issue:`40420`)
977978
- Bug in :class:`Series` backed by :class:`DatetimeArray` or :class:`TimedeltaArray` sometimes failing to set the array's ``freq`` to ``None`` (:issue:`41425`)
978979

pandas/core/apply.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -376,12 +376,10 @@ def agg_list_like(self) -> FrameOrSeriesUnion:
376376
raise ValueError("no results")
377377

378378
try:
379-
return concat(results, keys=keys, axis=1, sort=False)
379+
concatenated = concat(results, keys=keys, axis=1, sort=False)
380380
except TypeError as err:
381-
382381
# we are concatting non-NDFrame objects,
383382
# e.g. a list of scalars
384-
385383
from pandas import Series
386384

387385
result = Series(results, index=keys, name=obj.name)
@@ -390,6 +388,16 @@ def agg_list_like(self) -> FrameOrSeriesUnion:
390388
"cannot combine transform and aggregation operations"
391389
) from err
392390
return result
391+
else:
392+
# Concat uses the first index to determine the final indexing order.
393+
# The union of a shorter first index with the other indices causes
394+
# the index sorting to be different from the order of the aggregating
395+
# functions. Reindex if this is the case.
396+
index_size = concatenated.index.size
397+
full_ordered_index = next(
398+
result.index for result in results if result.index.size == index_size
399+
)
400+
return concatenated.reindex(full_ordered_index, copy=False)
393401

394402
def agg_dict_like(self) -> FrameOrSeriesUnion:
395403
"""

pandas/tests/apply/test_frame_apply.py

+35-4
Original file line numberDiff line numberDiff line change
@@ -1110,10 +1110,9 @@ def test_agg_multiple_mixed_no_warning():
11101110
with tm.assert_produces_warning(None):
11111111
result = mdf[["D", "C", "B", "A"]].agg(["sum", "min"])
11121112

1113-
# For backwards compatibility, the result's index is
1114-
# still sorted by function name, so it's ['min', 'sum']
1115-
# not ['sum', 'min'].
1116-
expected = expected[["D", "C", "B", "A"]]
1113+
# GH40420: the result of .agg should have an index that is sorted
1114+
# according to the arguments provided to agg.
1115+
expected = expected[["D", "C", "B", "A"]].reindex(["sum", "min"])
11171116
tm.assert_frame_equal(result, expected)
11181117

11191118

@@ -1521,6 +1520,38 @@ def test_apply_np_reducer(float_frame, op, how):
15211520
tm.assert_series_equal(result, expected)
15221521

15231522

1523+
def test_aggregation_func_column_order():
1524+
# GH40420: the result of .agg should have an index that is sorted
1525+
# according to the arguments provided to agg.
1526+
df = DataFrame(
1527+
[
1528+
("1", 1, 0, 0),
1529+
("2", 2, 0, 0),
1530+
("3", 3, 0, 0),
1531+
("4", 4, 5, 4),
1532+
("5", 5, 6, 6),
1533+
("6", 6, 7, 7),
1534+
],
1535+
columns=("item", "att1", "att2", "att3"),
1536+
)
1537+
1538+
def foo(s):
1539+
return s.sum() / 2
1540+
1541+
aggs = ["sum", foo, "count", "min"]
1542+
result = df.agg(aggs)
1543+
expected = DataFrame(
1544+
{
1545+
"item": ["123456", np.nan, 6, "1"],
1546+
"att1": [21.0, 10.5, 6.0, 1.0],
1547+
"att2": [18.0, 9.0, 6.0, 0.0],
1548+
"att3": [17.0, 8.5, 6.0, 0.0],
1549+
},
1550+
index=["sum", "foo", "count", "min"],
1551+
)
1552+
tm.assert_frame_equal(result, expected)
1553+
1554+
15241555
def test_apply_getitem_axis_1():
15251556
# GH 13427
15261557
df = DataFrame({"a": [0, 1, 2], "b": [1, 2, 3]})

0 commit comments

Comments
 (0)