Skip to content

Commit 948f247

Browse files
author
Marco Gorelli
committed
🐛 aggregations were getting overwritten if they had the same name
1 parent b529857 commit 948f247

File tree

3 files changed

+57
-4
lines changed

3 files changed

+57
-4
lines changed

doc/source/whatsnew/v1.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,7 @@ Groupby/resample/rolling
11321132
- Bug in :meth:`DataFrame.groupby` when using nunique on axis=1 (:issue:`30253`)
11331133
- Bug in :meth:`GroupBy.quantile` with multiple list-like q value and integer column names (:issue:`30289`)
11341134
- Bug in :meth:`GroupBy.pct_change` and :meth:`core.groupby.SeriesGroupBy.pct_change` causes ``TypeError`` when ``fill_method`` is ``None`` (:issue:`30463`)
1135+
- Bug in :meth:`SeriesGroupBy._aggregate_multiple_funcs` was resulting in aggregations being overwritten when they shared the same name (:issue:`30092`)
11351136

11361137
Reshaping
11371138
^^^^^^^^^

pandas/core/groupby/generic.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ def _aggregate_multiple_funcs(self, arg):
312312
arg = zip(columns, arg)
313313

314314
results = {}
315-
for name, func in arg:
315+
for idx, (name, func) in enumerate(arg):
316316
obj = self
317317

318318
# reset the cache so that we
@@ -321,13 +321,15 @@ def _aggregate_multiple_funcs(self, arg):
321321
obj = copy.copy(obj)
322322
obj._reset_cache()
323323
obj._selection = name
324-
results[name] = obj.aggregate(func)
324+
results[base.OutputKey(label=name, position=idx)] = obj.aggregate(func)
325325

326326
if any(isinstance(x, DataFrame) for x in results.values()):
327327
# let higher level handle
328-
return results
328+
return {key.label: value for key, value in results.items()}
329329

330-
return DataFrame(results, columns=columns)
330+
if results:
331+
return DataFrame(self._wrap_aggregated_output(results), columns=columns)
332+
return DataFrame(columns=columns)
331333

332334
def _wrap_series_output(
333335
self, output: Mapping[base.OutputKey, Union[Series, np.ndarray]], index: Index

pandas/tests/groupby/aggregate/test_aggregate.py

+50
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,56 @@ def test_agg_multiple_functions_maintain_order(df):
238238
tm.assert_index_equal(result.columns, exp_cols)
239239

240240

241+
def test_agg_multiple_functions_same_name(df):
242+
# GH 30880
243+
np.random.seed(1)
244+
df = tm.makeTimeDataFrame()
245+
result = df.resample("3D").agg(
246+
{"A": [functools.partial(np.std, ddof=0), functools.partial(np.std, ddof=1)]}
247+
)
248+
expected_index = pd.DatetimeIndex(
249+
[
250+
"2000-01-03",
251+
"2000-01-06",
252+
"2000-01-09",
253+
"2000-01-12",
254+
"2000-01-15",
255+
"2000-01-18",
256+
"2000-01-21",
257+
"2000-01-24",
258+
"2000-01-27",
259+
"2000-01-30",
260+
"2000-02-02",
261+
"2000-02-05",
262+
"2000-02-08",
263+
"2000-02-11",
264+
],
265+
dtype="datetime64[ns]",
266+
freq="3D",
267+
)
268+
expected_columns = pd.MultiIndex.from_tuples([("A", "std"), ("A", "std")])
269+
expected_values = [
270+
[1.03497007, 1.26757429],
271+
[0.96918813, 1.37063899],
272+
[2.02317523, 2.86120185],
273+
[0.44121013, 0.54036984],
274+
[0.0, np.nan],
275+
[0.80503606, 0.98596379],
276+
[0.0, np.nan],
277+
[0.3954067, 0.48427232],
278+
[0.27030073, 0.38226296],
279+
[1.12267144, 1.58769718],
280+
[0.18796289, 0.23020659],
281+
[0.0, np.nan],
282+
[0.3540029, 0.43356324],
283+
[0.0, np.nan],
284+
]
285+
expected = pd.DataFrame(
286+
expected_values, columns=expected_columns, index=expected_index
287+
)
288+
tm.assert_frame_equal(result, expected)
289+
290+
241291
def test_multiple_functions_tuples_and_non_tuples(df):
242292
# #1359
243293
funcs = [("foo", "mean"), "std"]

0 commit comments

Comments
 (0)