Repository: dask/dask
File: dask/dataframe/groupby.py (Python)

Code before:
            "This can be avoided by either filtering beforehand, or\n"
            "passing in the name of the column instead:\n"
            "\n"
            "df2 = df[df.foo < 0]\n"
            "df2.groupby(df2.bar)\n"
            "# or\n"
            "df[df.foo < 0].groupby('bar')\n"
            "\n"
            "For more information see dask GH issue #1876."
        )
        raise ValueError(msg)
    elif by is not None and len(by):
        # since we're coming through apply, `by` will be a tuple.
        # Pandas treats tuples as a single key, and lists as multiple keys
        # We want multiple keys
        if isinstance(by, str):
            by = [by]
        kwargs.update(by=list(by))
    return df.groupby(**kwargs)


def _groupby_slice_apply(df, grouper, key, func, *args, **kwargs):
    # No need to use raise if unaligned here - this is only called after
    # shuffling, which makes everything aligned already
    group_keys = kwargs.pop("group_keys", True)
    dropna = kwargs.pop("dropna", None)
    if dropna is not None:
        g = df.groupby(grouper, group_keys=group_keys, dropna=dropna)
    else:
        g = df.groupby(grouper, group_keys=group_keys)
    if key:
        g = g[key]
    return g.apply(func, *args, **kwargs)


def _groupby_slice_transform(df, grouper, key, func, *args, **kwargs):
    # No need to use raise if unaligned here - this is only called after
    # shuffling, which makes everything aligned already
    group_keys = kwargs.pop("group_keys", True)
    dropna = kwargs.pop("dropna", None)
    if dropna is not None:
        g = df.groupby(grouper, group_keys=group_keys, dropna=dropna)
    else:
        g = df.groupby(grouper, group_keys=group_keys)
    if key:
        g = g[key]

    # Cannot call transform on an empty dataframe
    if len(df) == 0:
        return g.apply(func, *args, **kwargs)


Review comment (suggestion):
Now that we have dropped support for Python 2 we can probably include these keywords explicitly in the signature.  Previously we avoided this because they were after a `*args`, which was not valid Python syntax.

Code after:
            "This can be avoided by either filtering beforehand, or\n"
            "passing in the name of the column instead:\n"
            "\n"
            "df2 = df[df.foo < 0]\n"
            "df2.groupby(df2.bar)\n"
            "# or\n"
            "df[df.foo < 0].groupby('bar')\n"
            "\n"
            "For more information see dask GH issue #1876."
        )
        raise ValueError(msg)
    elif by is not None and len(by):
        # since we're coming through apply, `by` will be a tuple.
        # Pandas treats tuples as a single key, and lists as multiple keys
        # We want multiple keys
        if isinstance(by, str):
            by = [by]
        kwargs.update(by=list(by))
    return df.groupby(**kwargs)


def _groupby_slice_apply(
    df, grouper, key, func, *args, group_keys=True, dropna=None, **kwargs
):
    # No need to use raise if unaligned here - this is only called after
    # shuffling, which makes everything aligned already
    dropna = {"dropna": dropna} if dropna is not None else {}
    g = df.groupby(grouper, group_keys=group_keys, **dropna)
    if key:
        g = g[key]
    return g.apply(func, *args, **kwargs)


def _groupby_slice_transform(
    df, grouper, key, func, *args, group_keys=True, dropna=None, **kwargs
):
    # No need to use raise if unaligned here - this is only called after
    # shuffling, which makes everything aligned already
    dropna = {"dropna": dropna} if dropna is not None else {}
    g = df.groupby(grouper, group_keys=group_keys, **dropna)
    if key:
        g = g[key]

    # Cannot call transform on an empty dataframe
    if len(df) == 0:
        return g.apply(func, *args, **kwargs)

    return g.transform(func, *args, **kwargs)


def _groupby_get_group(df, by_key, get_key, columns):