Skip to content

Commit f84483b

Browse files
author
Marco Gorelli
committed
🐛 aggregations were getting overwritten if they had the same name
1 parent 6f2c509 commit f84483b

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

11161117
Reshaping
11171118
^^^^^^^^^

pandas/core/groupby/generic.py

+6-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,15 @@ 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)
322322

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

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

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

0 commit comments

Comments
 (0)