Skip to content

Commit 5e9fe4e

Browse files
author
Marco Gorelli
committed
🐛 aggregations were getting overwritten if they had the same name
1 parent 6437f5e commit 5e9fe4e

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
@@ -1017,6 +1017,7 @@ Groupby/resample/rolling
10171017
- Bug in :meth:`DataFrame.groupby` when using nunique on axis=1 (:issue:`30253`)
10181018
- Bug in :meth:`GroupBy.quantile` with multiple list-like q value and integer column names (:issue:`30289`)
10191019
- Bug in :meth:`GroupBy.pct_change` and :meth:`core.groupby.SeriesGroupBy.pct_change` causes ``TypeError`` when ``fill_method`` is ``None`` (:issue:`30463`)
1020+
- Bug in :meth:`SeriesGroupBy._aggregate_multiple_funcs` was resulting in aggregations being overwritten when they shared the same name (:issue:`30092`)
10201021

10211022
Reshaping
10221023
^^^^^^^^^

pandas/core/groupby/generic.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def _aggregate_multiple_funcs(self, arg):
309309
arg = zip(columns, arg)
310310

311311
results = {}
312-
for name, func in arg:
312+
for idx, (name, func) in enumerate(arg):
313313
obj = self
314314

315315
# reset the cache so that we
@@ -318,13 +318,16 @@ def _aggregate_multiple_funcs(self, arg):
318318
obj = copy.copy(obj)
319319
obj._reset_cache()
320320
obj._selection = name
321-
results[name] = obj.aggregate(func)
321+
results[base.OutputKey(label=name, position=idx)] = obj.aggregate(func)
322+
oldresults[name] = obj.aggregate(func)
322323

323324
if any(isinstance(x, DataFrame) for x in results.values()):
324325
# let higher level handle
325-
return results
326+
return {key.label: value for key, value in results.items()}
326327

327-
return DataFrame(results, columns=columns)
328+
if results:
329+
return DataFrame(self._wrap_aggregated_output(results), columns=columns)
330+
return DataFrame(columns=columns)
328331

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

pandas/tests/groupby/aggregate/test_aggregate.py

+49
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,55 @@ def test_agg_multiple_functions_maintain_order(df):
239239
tm.assert_index_equal(result.columns, exp_cols)
240240

241241

242+
def test_agg_multiple_functions_same_name(df):
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+
242291
def test_multiple_functions_tuples_and_non_tuples(df):
243292
# #1359
244293
funcs = [("foo", "mean"), "std"]

0 commit comments

Comments
 (0)