Skip to content

Fix groupby().parallel_apply() passing grouping columns on pandas >= 3.0 - #282

Open
LalwaniPalash wants to merge 1 commit into
nalepae:masterfrom
LalwaniPalash:fix/groupby-apply-exclusions-pandas3
Open

Fix groupby().parallel_apply() passing grouping columns on pandas >= 3.0#282
LalwaniPalash wants to merge 1 commit into
nalepae:masterfrom
LalwaniPalash:fix/groupby-apply-exclusions-pandas3

Conversation

@LalwaniPalash

Copy link
Copy Markdown

Problem

Since pandas 3.0, DataFrameGroupBy.apply operates on _obj_with_exclusions — the grouping
columns are no longer passed to the applied function. Iterating a DataFrameGroupBy still
yields them, and that is how pandarallel builds its chunks, so parallel_apply still passes
them.

The result is a silent divergence — no exception, just a different answer:

import pandas as pd, numpy as np
from pandarallel import pandarallel
pandarallel.initialize(nb_workers=2, progress_bar=False)

df = pd.DataFrame(dict(a=np.random.randint(1, 4, 20),
                       b=np.random.rand(20),
                       c=np.random.rand(20)))

df.groupby('a').apply(lambda g: list(g.columns)).iloc[0]
# ['b', 'c']         <- pandas

df.groupby('a').parallel_apply(lambda g: list(g.columns)).iloc[0]
# ['a', 'b', 'c']    <- pandarallel

Any user function that iterates columns, calls .sum() / .mean() across the frame, or builds
a result from df.shape gets a different answer from parallel_apply than from apply.

Fix

Restrict each group to the columns apply would have used, gated on the pandas version so
behaviour on pandas < 3.0 is unchanged. Uses the existing get_pandas_version() helper, matching
the version-gating already used in reduce() in this file.

Tests

func_dataframe_groupby_apply read df.b, but test_dataframe_groupby_apply also covers
groupby(["a", "b"]) — where b is now a grouping column. On pandas 3.0 that fixture raises
AttributeError in the reference apply call, before parallel_apply is reached. Switched
the fixture to column c, which is never a grouping column in these tests.

Verification

pandas 3.0.3, Python 3.14.6:

before after
-k groupby 8 failed, 40 passed 48 passed
full suite 24 failed, 193 passed 16 failed, 201 passed

The 16 remaining failures are all test_dataframe_applymapDataFrame.applymap was removed
in pandas 3.0. That is #280's scope, not this PR's. With #280 applied on top of this branch the
full suite is 217 passed, 0 failed.

Note on CI

CI is currently red on this repo independently of this change — the matrix targets ubuntu-20.04
(retired by GitHub, jobs are cancelled before running) and Python 3.7.9–3.10.8. The most recent
run, on #280, failed for this reason. The matrix also tops out at pandas 2.0, so it would not
have caught this bug and will not exercise this fix.

Because the change is gated on get_pandas_version() >= (3, 0), it is a no-op on every
combination the matrix currently pins — so it cannot regress them.

Happy to send a separate PR refreshing the CI matrix (current runners, supported Python versions,
and a pandas 3.x entry) if that would be useful.

…das >= 3.0

Since pandas 3.0, DataFrameGroupBy.apply operates on _obj_with_exclusions, so the
grouping columns are no longer passed to the applied function. Iterating a
DataFrameGroupBy still yields them, which is how pandarallel builds its chunks, so
parallel_apply kept passing them.

This produced a silent divergence rather than an error: user functions that iterate
columns or aggregate across the frame got different results from parallel_apply than
from apply.

Restrict each group to the columns apply would have used, gated on the pandas version
so behaviour on pandas < 3.0 is unchanged.

The groupby test fixture read df.b, but the test also covers groupby(["a", "b"]) where
b is now a grouping column, making the reference apply() call raise on pandas 3.0.
Switched the fixture to column c, which is never a grouping column in these tests.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request aligns DataFrameGroupBy.parallel_apply() behavior with pandas ≥ 3.0’s DataFrameGroupBy.apply() by ensuring grouping columns are not included in the DataFrame passed to the user function (matching pandas’ _obj_with_exclusions behavior). It also updates the affected test fixture to avoid referencing a column that becomes a grouping column in one of the groupby test cases under pandas 3.0.

Changes:

  • Update DataFrameGroupBy.Apply.get_chunks() to slice each yielded group to dataframe_groupby._obj_with_exclusions.columns when pandas ≥ 3.0.
  • Adjust func_dataframe_groupby_apply test fixture to operate on column c (not b) so reference apply doesn’t fail in the groupby(["a", "b"]) test case under pandas 3.0.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
pandarallel/data_types/dataframe_groupby.py Ensures group chunks match pandas ≥ 3.0 apply() semantics by excluding grouping columns before invoking the user function.
tests/test_pandarallel.py Updates the groupby-apply fixture to avoid depending on a column that can become excluded as a grouping column in pandas ≥ 3.0.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants