pandas-dev/pandas · error · ValueError

Function did not transform

Error message

Function did not transform

What it means

Raised inside `Apply.transform` when the function returns a value that is either not a Series/DataFrame or whose index does not match the input object's index. `transform` is contract-bound to return output with the same axis as the input (it must broadcast back); returning a scalar or a reindexed object violates this contract.

Source

Thrown at pandas/core/apply.py:406

        try:
            result = self.transform_str_or_callable(func)
        except TypeError:
            raise
        except Exception as err:
            raise ValueError("Transform function failed") from err

        # Functions that transform may return empty Series/DataFrame
        # when the dtype is not appropriate
        if (
            isinstance(result, (ABCSeries, ABCDataFrame))
            and result.empty
            and not obj.empty
        ):
            raise ValueError("Transform function failed")
        if not isinstance(result, (ABCSeries, ABCDataFrame)) or not result.index.equals(
            obj.index
        ):
            raise ValueError("Function did not transform")

        return result

    def transform_dict_like(self, func) -> DataFrame:
        """
        Compute transform in the case of a dict-like func
        """

        obj = self.obj
        args = self.args
        kwargs = self.kwargs

        # transform is currently only for Series/DataFrame
        assert isinstance(obj, ABCNDFrame)

        if len(func) == 0:
            raise ValueError("No transform functions were provided")

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. If you want one value per group/column, use `agg` (or `apply`) instead of `transform`.
  2. Ensure the function returns a Series with the same index as its input: e.g. `lambda s: s - s.mean()`.
  3. Avoid index-mutating operations (reset_index, sort_values without restoring index) inside the transform function.

Example fix

# before
df.groupby('g')['v'].transform(lambda s: s.sum())  # scalar per group
# after
df.groupby('g')['v'].transform(lambda s: s.fillna(s.mean()))
# or use agg for reduction
df.groupby('g')['v'].agg('sum')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

def is_valid_transform(func, s):
    """Verify func returns same-index Series for transform contract."""
    out = func(s)
    return isinstance(out, pd.Series) and out.index.equals(s.index)

sample = df[df.columns[0]]
if not is_valid_transform(my_func, sample):
    # use agg instead
    result = df.agg(my_func)
else:
    df.transform(my_func)

Type guard

def preserves_index(out, original) -> bool:
    import pandas as pd
    return isinstance(out, pd.Series) and out.index.equals(original.index)

Try / catch

try:
    df.transform(func)
except ValueError as e:
    if 'Function did not transform' in str(e):
        df.agg(func)  # fall back to aggregation semantics
    else:
        raise

Prevention

When it happens

Trigger: `df.transform(lambda s: s.sum())` — returns a scalar per column, not same-length output. `df.transform(lambda s: s.reset_index(drop=True))` — breaks index alignment. Any function returning a length-mismatched or non-NDFrame object.

Common situations: Confusing `transform` with `agg` (the most common cause): developers use transform when they want a single aggregated value per group/column. Also functions that internally sort/reset the index, or that return Python primitives.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/249f19766e8cbd26. Report an issue: GitHub.