将函数名称作为字符串传递给 Pandas GroupBy 聚合

Vin*_*ius 5 python pandas pandas-groupby

在 Pandas 中,可以通过传递字符串别名来告诉您如何聚合数据('min'在下面的示例中)。从文档中,您有:

df.groupby('A').agg('min')
Run Code Online (Sandbox Code Playgroud)

很明显这是在做什么,但让我很恼火的是,我在文档中找不到这些字符串别名的列表以及它们的作用的描述。

有谁知道这些别名的参考吗?

Mic*_*ado 5

字符串方法名称可以引用正在操作的对象的任何方法。此外,如果对象有一个__array__属性(据我所知,如果您调用aggtransform直接调用,而不是使用groupbyresamplerolling等),它可以引用 numpy 模块级命名空间中的任何内容(例如 中的任何内容np.__all__)。这并不是说所有可以引用的东西都可以工作,但是您实际上可以引用这些命名空间中的任何一个。

例子

这是一个示例数据框:

In [9]: df = pd.DataFrame({'abc': list('aaaabbcccc'), 'data': np.random.random(size=10)})

In [10]: df
Out[10]:
  abc      data
0   a  0.800357
1   a  0.619654
2   a  0.448895
3   a  0.610645
4   b  0.985249
5   b  0.179411
6   c  0.173734
7   c  0.420767
8   c  0.789766
9   c  0.525486
Run Code Online (Sandbox Code Playgroud)

.agg具有和 的DataFrame 和 Series 方法.transform

这可以使用任何 DataFrame 方法进行聚合或转换(只要适用aggtransform遵循形状规则)。

当然,还有我们都熟悉的聚合方法:

In [93]: df.agg("sum")
Out[93]:
abc     aaaabbcccc
data      5.553964
dtype: object
Run Code Online (Sandbox Code Playgroud)

但您确实可以尝试一下 DataFrame/Series API 中的任何内容:

In [95]: df.transform("shift")
Out[95]:
   abc      data
0  NaN       NaN
1    a  0.800357
2    a  0.619654
3    a  0.448895
4    a  0.610645
5    b  0.985249
6    b  0.179411
7    c  0.173734
8    c  0.420767
9    c  0.789766

In [102]: df.agg("dtypes")
Out[102]:
abc      object
data    float64
dtype: object
Run Code Online (Sandbox Code Playgroud)

.agg带有and的 Numpy 方法.transform

此外,当直接使用 pandas 对象时,我们也可以使用 numpy 全局方法。其中许多并不按您预期的方式工作,因此用户要小心:

In [101]: df.data.transform("expm1")
Out[101]:
0    1.226334
1    0.858285
2    0.566580
3    0.841620
4    1.678479
5    0.196512
6    0.189739
7    0.523129
8    1.202882
9    0.691281
Name: data, dtype: float64

In [103]: df.agg("rot90")
Out[103]:
array([[0.8003565068959021, 0.619653790821421, 0.44889504260755986,
        0.6106454343417287, 0.9852492020323964, 0.17941064387786554,
        0.17373389351532997, 0.42076690363942437, 0.7897663627044728,
        0.5254860156343195],
       ['a', 'a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c']], dtype=object)

In [107]: df.agg("meshgrid")
Out[107]:
[array(['a', 0.8003565068959021, 'a', 0.619653790821421, 'a',
        0.44889504260755986, 'a', 0.6106454343417287, 'b',
        0.9852492020323964, 'b', 0.17941064387786554, 'c',
        0.17373389351532997, 'c', 0.42076690363942437, 'c',
        0.7897663627044728, 'c', 0.5254860156343195], dtype=object)]

In [109]: df.agg("diag")
Out[109]: array(['a', 0.619653790821421], dtype=object)
Run Code Online (Sandbox Code Playgroud)

可用于 GroupBy、Window 和 Resample 操作的方法

这些 numpy 方法不能直接用于GroupbyRollingExpandingResample等对象。但您仍然可以调用这些对象可用的 pandas API 中的任何内容:

In [117]: df.groupby('abc').agg("dtypes")
Out[117]:
        data
abc
a    float64
b    float64
c    float64

In [129]: df.groupby("abc").agg("ohlc")
Out[129]:
         data
         open      high       low     close
abc
a    0.800357  0.800357  0.448895  0.610645
b    0.985249  0.985249  0.179411  0.179411
c    0.173734  0.789766  0.173734  0.525486

In [137]: df.rolling(3).data.agg("quantile", 0.9)
Out[137]:
0         NaN
1         NaN
2    0.764216
3    0.617852
4    0.910328
5    0.910328
6    0.824081
7    0.372496
8    0.715966
9    0.736910
Name: data, dtype: float64
Run Code Online (Sandbox Code Playgroud)

请注意,pandas API 中与对象范围相关的部分是GroupbyWindowResampling对象本身,而不是 DataFrame 或 Series。因此,请检查这些对象的 API 以获取完整的 API 参考。

执行

深埋在 pandas 内部,您可以将字符串聚合操作的处理追溯到该函数的几个变体,目前位于pandas.core.apply._try_aggregate_string_function


    def _try_aggregate_string_function(self, obj, arg: str, *args, **kwargs):
        """
        if arg is a string, then try to operate on it:
        - try to find a function (or attribute) on ourselves
        - try to find a numpy function
        - raise
        """
        assert isinstance(arg, str)

        f = getattr(obj, arg, None)
        if f is not None:
            if callable(f):
                return f(*args, **kwargs)

            # people may try to aggregate on a non-callable attribute
            # but don't let them think they can pass args to it
            assert len(args) == 0
            assert len([kwarg for kwarg in kwargs if kwarg not in ["axis"]]) == 0
            return f

        f = getattr(np, arg, None)
        if f is not None and hasattr(obj, "__array__"):
            # in particular exclude Window
            return f(obj, *args, **kwargs)

        raise AttributeError(
            f"'{arg}' is not a valid function for '{type(obj).__name__}' object"
        )
Run Code Online (Sandbox Code Playgroud)

getattr(obj, f)同样,在测试套件和内部的许多地方,都使用了逻辑,其中obj是数据结构,f是字符串函数名称。


Aad*_*waj 0

https://cmdlinetips.com/2019/10/pandas-groupby-13-functions-to-aggregate/

该链接提供了 13 个 agg 函数。但是,您也可以使用 lambda 函数。例如,

df = pd.DataFrame({"A": [1, 1, 2, 2,],
    "B": [1, 2, 3, 4],
    "C": [0.362838, 0.227877, 1.267767, -0.562860],})
df.groupby('A').agg(lambda x:sum(x))
Run Code Online (Sandbox Code Playgroud)