apache/beam · error · NotImplementedError

String functions are not yet supported in transform.

Error message

String functions are not yet supported in transform.

What it means

Apache Beam's DeferredGroupBy.transform() requires `fn` to be a Python callable. When a string like 'sum' or a non-callable is passed (as pandas allows in some contexts), Beam cannot build the deferred transformation and raises NotImplementedError with the 'String functions are not yet supported in transform.' message, even if the argument is simply any non-callable.

Solutions

  1. Pass a callable, e.g. df.groupby('k').transform(lambda s: s - s.mean()) instead of a string.
  2. If a string aggregation is what you need, use groupby(...).agg(...) which supports string aggregation names via _handle_agg_function.
  3. Check the argument is callable before calling: isinstance(fn, collections.abc.Callable).

Example fix

# before
df.groupby('k').transform('mean')
# after
df.groupby('k').transform(lambda s: s.mean())
Defensive patterns

Strategy: type-guard

Validate before calling

import collections.abc
if not isinstance(fn, collections.abc.Callable):
    raise TypeError('transform requires a callable, got %r' % (fn,))

Type guard

def is_callable_fn(fn) -> bool:
    return isinstance(fn, collections.abc.Callable)

Try / catch

try:
    out = beam_df.groupby('k').transform(fn)
except NotImplementedError as e:
    if 'not yet supported in transform' in str(e):
        out = beam_df.groupby('k').agg(fn if callable(fn) else lambda s: getattr(s, fn)())

Prevention

When it happens

Trigger: Calling df.groupby(...).transform('some_string') or transform(anything_not_callable) on a Beam deferred DataFrame; string aggregation-style names accepted by pandas GroupBy.transform are not supported here.

Common situations: Porting existing pandas pipeline code to Beam where transform was invoked with a string function name; confusing GroupBy.transform with GroupBy.agg, which does accept string aggregation names.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/fde1dd5df95ba1c7. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/dataframe/frames.py:4395

            [self._ungrouped_with_index],
            proxy=proxy,
            requires_partition_by=partitionings.Index(grouping_indexes +
                                                      grouping_columns),
            preserves_partition_by=partitionings.Index(grouping_indexes)))


  @frame_base.with_docs_from(DataFrameGroupBy)
  def transform(self, fn, *args, **kwargs):
    """Note that ``func`` will be called once during pipeline construction time
    with an empty pandas object, so take care if ``func`` has a side effect.

    When called with an empty pandas object, ``func`` is expected to return an
    object of the same type as what will be returned when the pipeline is
    processing actual data. The result should have the same type and name (for
    a Series) or column types and names (for a DataFrame) as the actual
    results."""
    if not callable(fn):
      raise NotImplementedError(
          "String functions are not yet supported in transform.")

    if self._grouping_columns and not self._projection:
      grouping_columns = self._grouping_columns
      def fn_wrapper(x, *args, **kwargs):
        x = x.droplevel(grouping_columns)
        return fn(x, *args, **kwargs)
    else:
      fn_wrapper = fn

    project = _maybe_project_func(self._projection)
    group_keys = self._group_keys

    # pandas cannot execute fn to determine the right proxy.
    # We run user fn on a proxy here to detect the return type and generate the
    # proxy.
    result = fn_wrapper(project(self._ungrouped_with_index.proxy()))
    parent_frame = self._ungrouped.args()[0].proxy()

View on GitHub (pinned to 12126d8942)