通过组进行迭代
有了 GroupBy 对象,通过分组数据进行迭代非常自然,类似于itertools.groupby()
的操作:
In [74]: grouped = df.groupby('A') In [75]: for name, group in grouped: ....: print(name) ....: print(group) ....: bar A B C D 1 bar one 0.254161 1.511763 3 bar three 0.215897 -0.990582 5 bar two -0.077118 1.211526 foo A B C D 0 foo one -0.575247 1.346061 2 foo two -1.143704 1.627081 4 foo two 1.193555 -0.441652 6 foo one -0.408530 0.268520 7 foo three -0.862495 0.024580
在按多个键分组的情况下,组名将是一个元组:
In [76]: for name, group in df.groupby(['A', 'B']): ....: print(name) ....: print(group) ....: ('bar', 'one') A B C D 1 bar one 0.254161 1.511763 ('bar', 'three') A B C D 3 bar three 0.215897 -0.990582 ('bar', 'two') A B C D 5 bar two -0.077118 1.211526 ('foo', 'one') A B C D 0 foo one -0.575247 1.346061 6 foo one -0.408530 0.268520 ('foo', 'three') A B C D 7 foo three -0.862495 0.02458 ('foo', 'two') A B C D 2 foo two -1.143704 1.627081 4 foo two 1.193555 -0.441652
参见通过组进行迭代。
选择一个组
可以使用DataFrameGroupBy.get_group()
选择单个组:
In [77]: grouped.get_group("bar") Out[77]: A B C D 1 bar one 0.254161 1.511763 3 bar three 0.215897 -0.990582 5 bar two -0.077118 1.211526
或者对于在多列上分组的对象:
In [78]: df.groupby(["A", "B"]).get_group(("bar", "one")) Out[78]: A B C D 1 bar one 0.254161 1.511763
聚合
聚合是 GroupBy 操作,它减少了分组对象的维度。聚合的结果是每列在组中的一个标量值,或者至少被视为这样。例如,产生值组中每列的总和。
In [79]: animals = pd.DataFrame( ....: { ....: "kind": ["cat", "dog", "cat", "dog"], ....: "height": [9.1, 6.0, 9.5, 34.0], ....: "weight": [7.9, 7.5, 9.9, 198.0], ....: } ....: ) ....: In [80]: animals Out[80]: kind height weight 0 cat 9.1 7.9 1 dog 6.0 7.5 2 cat 9.5 9.9 3 dog 34.0 198.0 In [81]: animals.groupby("kind").sum() Out[81]: height weight kind cat 18.6 17.8 dog 40.0 205.5
在结果中,默认情况下组的键出现在索引中。可以通过传递as_index=False
来将其包含在列中。
In [82]: animals.groupby("kind", as_index=False).sum() Out[82]: kind height weight 0 cat 18.6 17.8 1 dog 40.0 205.5
内置聚合方法
许多常见的聚合操作内置在 GroupBy 对象中作为方法。在下面列出的方法中,带有*
的方法没有高效的、GroupBy 特定的实现。
方法 | 描述 |
any() |
计算组中任何值是否为真 |
all() |
计算组中所有值是否为真 |
count() |
计算组中非 NA 值的数量 |
cov() * |
计算组的协方差 |
first() |
计算每个组中首次出现的值 |
idxmax() |
计算每个组中最大值的索引 |
idxmin() |
计算每个组中最小值的索引 |
last() |
计算每个组中最后出现的值 |
max() |
计算每个组中的最大值 |
mean() |
计算每个组的平均值 |
median() |
计算每个组的中位数 |
min() |
计算每个组中的最小值 |
nunique() |
计算每个组中唯一值的数量 |
prod() |
计算每个组中值的乘积 |
quantile() |
计算每个组中值的给定分位数 |
sem() |
计算每个组中值的平均标准误差 |
size() |
计算每个组中的值的数量 |
skew() * |
计算每个组中值的偏度 |
std() |
计算每个组中值的标准偏差 |
sum() |
计算每个组中值的总和 |
var() |
计算每个组中值的方差 |
一些示例:
In [83]: df.groupby("A")[["C", "D"]].max() Out[83]: C D A bar 0.254161 1.511763 foo 1.193555 1.627081 In [84]: df.groupby(["A", "B"]).mean() Out[84]: C D A B bar one 0.254161 1.511763 three 0.215897 -0.990582 two -0.077118 1.211526 foo one -0.491888 0.807291 three -0.862495 0.024580 two 0.024925 0.592714
另一个聚合示例是计算每个组的大小。这包含在 GroupBy 中作为size
方法。它返回一个 Series,其索引由组名组成,值是每个组的大小。
In [85]: grouped = df.groupby(["A", "B"]) In [86]: grouped.size() Out[86]: A B bar one 1 three 1 two 1 foo one 2 three 1 two 2 dtype: int64
DataFrameGroupBy.describe()
方法本身不是一个减少器,但可以方便地生成关于每个组的摘要统计信息的集合。
In [87]: grouped.describe() Out[87]: C ... D count mean std ... 50% 75% max A B ... bar one 1.0 0.254161 NaN ... 1.511763 1.511763 1.511763 three 1.0 0.215897 NaN ... -0.990582 -0.990582 -0.990582 two 1.0 -0.077118 NaN ... 1.211526 1.211526 1.211526 foo one 2.0 -0.491888 0.117887 ... 0.807291 1.076676 1.346061 three 1.0 -0.862495 NaN ... 0.024580 0.024580 0.024580 two 2.0 0.024925 1.652692 ... 0.592714 1.109898 1.627081 [6 rows x 16 columns]
另一个聚合示例是计算每个组的唯一值的数量。这类似于DataFrameGroupBy.value_counts()
函数,只是它只计算唯一值的数量。
In [88]: ll = [['foo', 1], ['foo', 2], ['foo', 2], ['bar', 1], ['bar', 1]] In [89]: df4 = pd.DataFrame(ll, columns=["A", "B"]) In [90]: df4 Out[90]: A B 0 foo 1 1 foo 2 2 foo 2 3 bar 1 4 bar 1 In [91]: df4.groupby("A")["B"].nunique() Out[91]: A bar 1 foo 2 Name: B, dtype: int64
注意
聚合函数不会在as_index=True
(默认情况下)时将聚合的组作为命名列返回。分组的列将是返回对象的索引。
传递as_index=False
将返回聚合的组作为命名列,无论它们在输入中是命名的索引还是列。### aggregate()
方法
注意
aggregate()
方法可以接受许多不同类型的输入。本节详细介绍了使用字符串别名进行各种 GroupBy 方法的聚合;其他输入在下面的各节中详细说明。
pandas 实现的任何减少方法都可以作为字符串传递给aggregate()
。鼓励用户使用简写agg
。它将操作,就好像调用了相应的方法一样。
In [92]: grouped = df.groupby("A") In [93]: grouped[["C", "D"]].aggregate("sum") Out[93]: C D A bar 0.392940 1.732707 foo -1.796421 2.824590 In [94]: grouped = df.groupby(["A", "B"]) In [95]: grouped.agg("sum") Out[95]: C D A B bar one 0.254161 1.511763 three 0.215897 -0.990582 two -0.077118 1.211526 foo one -0.983776 1.614581 three -0.862495 0.024580 two 0.049851 1.185429
聚合的结果将具有组名作为新索引。在多个键的情况下,默认情况下结果是 MultiIndex。如上所述,可以通过使用as_index
选项来更改这一点:
In [96]: grouped = df.groupby(["A", "B"], as_index=False) In [97]: grouped.agg("sum") Out[97]: A B C D 0 bar one 0.254161 1.511763 1 bar three 0.215897 -0.990582 2 bar two -0.077118 1.211526 3 foo one -0.983776 1.614581 4 foo three -0.862495 0.024580 5 foo two 0.049851 1.185429 In [98]: df.groupby("A", as_index=False)[["C", "D"]].agg("sum") Out[98]: A C D 0 bar 0.392940 1.732707 1 foo -1.796421 2.824590
请注意,您可以使用DataFrame.reset_index()
DataFrame 函数来实现与列名存储在结果MultiIndex
中相同的结果,尽管这将产生额外的副本。
In [99]: df.groupby(["A", "B"]).agg("sum").reset_index() Out[99]: A B C D 0 bar one 0.254161 1.511763 1 bar three 0.215897 -0.990582 2 bar two -0.077118 1.211526 3 foo one -0.983776 1.614581 4 foo three -0.862495 0.024580 5 foo two 0.049851 1.185429 ```### 使用用户定义函数进行聚合 用户还可以为自定义聚合提供自己的用户定义函数(UDFs)。 警告 在使用 UDF 进行聚合时,UDF 不应该改变提供的`Series`。有关更多信息,请参阅使用用户定义函数(UDF)方法进行变异。 注意 使用 UDF 进行聚合通常比在 GroupBy 上使用 pandas 内置方法性能较差。考虑将复杂操作拆分为一系列利用内置方法的操作链。 ```py In [100]: animals Out[100]: kind height weight 0 cat 9.1 7.9 1 dog 6.0 7.5 2 cat 9.5 9.9 3 dog 34.0 198.0 In [101]: animals.groupby("kind")[["height"]].agg(lambda x: set(x)) Out[101]: height kind cat {9.1, 9.5} dog {34.0, 6.0}
结果 dtype 将反映聚合函数的 dtype。如果不同组的结果具有不同的 dtype,则将以与DataFrame
构造相同的方式确定公共 dtype。
In [102]: animals.groupby("kind")[["height"]].agg(lambda x: x.astype(int).sum()) Out[102]: height kind cat 18 dog 40 ```### 一次应用多个函数 在分组的`Series`上,您可以将函数列表或字典传递给`SeriesGroupBy.agg()`,输出一个 DataFrame: ```py In [103]: grouped = df.groupby("A") In [104]: grouped["C"].agg(["sum", "mean", "std"]) Out[104]: sum mean std A bar 0.392940 0.130980 0.181231 foo -1.796421 -0.359284 0.912265
在分组的DataFrame
上,您可以将函数列表传递给DataFrameGroupBy.agg()
,以对每列进行聚合,从而产生具有分层列索引的聚合结果:
In [105]: grouped[["C", "D"]].agg(["sum", "mean", "std"]) Out[105]: C D sum mean std sum mean std A bar 0.392940 0.130980 0.181231 1.732707 0.577569 1.366330 foo -1.796421 -0.359284 0.912265 2.824590 0.564918 0.884785
结果聚合以函数本身命名。如果需要重命名,则可以像这样为Series
添加一个链接操作:
In [106]: ( .....: grouped["C"] .....: .agg(["sum", "mean", "std"]) .....: .rename(columns={"sum": "foo", "mean": "bar", "std": "baz"}) .....: ) .....: Out[106]: foo bar baz A bar 0.392940 0.130980 0.181231 foo -1.796421 -0.359284 0.912265
对于分组的DataFrame
,您可以以类似的方式重命名:
In [107]: ( .....: grouped[["C", "D"]].agg(["sum", "mean", "std"]).rename( .....: columns={"sum": "foo", "mean": "bar", "std": "baz"} .....: ) .....: ) .....: Out[107]: C D foo bar baz foo bar baz A bar 0.392940 0.130980 0.181231 1.732707 0.577569 1.366330 foo -1.796421 -0.359284 0.912265 2.824590 0.564918 0.884785
注意
通常情况下,输出列名应该是唯一的,但是 pandas 允许您将相同的函数(或两个具有相同名称的函数)应用于同一列。
In [108]: grouped["C"].agg(["sum", "sum"]) Out[108]: sum sum A bar 0.392940 0.392940 foo -1.796421 -1.796421
pandas 还允许您提供多个 lambda。在这种情况下,pandas 将破坏(无名)lambda 函数的名称,对每个后续 lambda 添加_
。
In [109]: grouped["C"].agg([lambda x: x.max() - x.min(), lambda x: x.median() - x.mean()]) Out[109]: <lambda_0> <lambda_1> A bar 0.331279 0.084917 foo 2.337259 -0.215962 ```### 命名聚合 为了支持*控制输出列名的特定列聚合*,pandas 在`DataFrameGroupBy.agg()` 和`SeriesGroupBy.agg()` 中接受特殊语法,称为“命名聚合”,其中 + 关键字是*输出*列名 + 值是元组,其第一个元素是要选择的列,第二个元素是要应用于该列的聚合。pandas 提供了带有字段`['column', 'aggfunc']`的`NamedAgg` 命名元组,以使参数更清晰。通常,聚合可以是可调用的或字符串别名。 ```py In [110]: animals Out[110]: kind height weight 0 cat 9.1 7.9 1 dog 6.0 7.5 2 cat 9.5 9.9 3 dog 34.0 198.0 In [111]: animals.groupby("kind").agg( .....: min_height=pd.NamedAgg(column="height", aggfunc="min"), .....: max_height=pd.NamedAgg(column="height", aggfunc="max"), .....: average_weight=pd.NamedAgg(column="weight", aggfunc="mean"), .....: ) .....: Out[111]: min_height max_height average_weight kind cat 9.1 9.5 8.90 dog 6.0 34.0 102.75
NamedAgg
只是一个namedtuple
。也允许使用普通元组。
In [112]: animals.groupby("kind").agg( .....: min_height=("height", "min"), .....: max_height=("height", "max"), .....: average_weight=("weight", "mean"), .....: ) .....: Out[112]: min_height max_height average_weight kind cat 9.1 9.5 8.90 dog 6.0 34.0 102.75
如果您想要的列名不是有效的 Python 关键字,请构建一个字典并解压关键字参数
In [113]: animals.groupby("kind").agg( .....: **{ .....: "total weight": pd.NamedAgg(column="weight", aggfunc="sum") .....: } .....: ) .....: Out[113]: total weight kind cat 17.8 dog 205.5
在使用命名聚合时,额外的关键字参数不会传递给聚合函数;只有(column, aggfunc)
对作为**kwargs
传递。如果您的聚合函数需要额外的参数,可以使用functools.partial()
部分应用它们。
命名聚合对于 Series 分组聚合也是有效的。在这种情况下,没有列选择,因此值只是函数。
In [114]: animals.groupby("kind").height.agg( .....: min_height="min", .....: max_height="max", .....: ) .....: Out[114]: min_height max_height kind cat 9.1 9.5 dog 6.0 34.0
对 DataFrame 列应用不同的函数
通过将字典传递给aggregate
,您可以对 DataFrame 的列应用不同的聚合:
In [115]: grouped.agg({"C": "sum", "D": lambda x: np.std(x, ddof=1)}) Out[115]: C D A bar 0.392940 1.366330 foo -1.796421 0.884785
函数名称也可以是字符串。为了使字符串有效,必须在 GroupBy 上实现它:
In [116]: grouped.agg({"C": "sum", "D": "std"}) Out[116]: C D A bar 0.392940 1.366330 foo -1.796421 0.884785
内置聚合方法
许多常见的聚合在 GroupBy 对象中作为方法内置。在下面列出的方法中,带有*
的方法 没有 高效的、GroupBy 特定的实现。
方法 | 描述 |
any() |
计算组中任何值是否为真 |
all() |
计算组中所有值是否为真 |
count() |
计算组中非 NA 值的数量 |
cov() * |
计算组的协方差 |
first() |
计算每个组中首次出现的值 |
idxmax() |
计算每个组中最大值的索引 |
idxmin() |
计算每个组中最小值的索引 |
last() |
计算每个组中最后出现的值 |
max() |
计算每个组中的最大值 |
mean() |
计算每个组的均值 |
median() |
计算每个组的中位数 |
min() |
计算每个组中的最小值 |
nunique() |
计算每个组中唯一值的数量 |
prod() |
计算每个组中值的乘积 |
quantile() |
计算每个组中值的给定分位数 |
sem() |
计算每个组中值的均值标准误差 |
size() |
计算每个组中值的数量 |
skew() * |
计算每个组中值的偏度 |
std() |
计算每个组中值的标准差 |
sum() |
计算每个组中值的总和 |
var() |
计算每个组中值的方差 |
一些示例:
In [83]: df.groupby("A")[["C", "D"]].max() Out[83]: C D A bar 0.254161 1.511763 foo 1.193555 1.627081 In [84]: df.groupby(["A", "B"]).mean() Out[84]: C D A B bar one 0.254161 1.511763 three 0.215897 -0.990582 two -0.077118 1.211526 foo one -0.491888 0.807291 three -0.862495 0.024580 two 0.024925 0.592714
另一个聚合示例是计算每个组的大小。这包含在 GroupBy 中作为size
方法。它返回一个 Series,其索引由组名组成,值是每个组的大小。
In [85]: grouped = df.groupby(["A", "B"]) In [86]: grouped.size() Out[86]: A B bar one 1 three 1 two 1 foo one 2 three 1 two 2 dtype: int64
虽然DataFrameGroupBy.describe()
方法本身不是一个缩减器,但它可以用于方便地生成关于每个组的摘要统计信息的集合。
In [87]: grouped.describe() Out[87]: C ... D count mean std ... 50% 75% max A B ... bar one 1.0 0.254161 NaN ... 1.511763 1.511763 1.511763 three 1.0 0.215897 NaN ... -0.990582 -0.990582 -0.990582 two 1.0 -0.077118 NaN ... 1.211526 1.211526 1.211526 foo one 2.0 -0.491888 0.117887 ... 0.807291 1.076676 1.346061 three 1.0 -0.862495 NaN ... 0.024580 0.024580 0.024580 two 2.0 0.024925 1.652692 ... 0.592714 1.109898 1.627081 [6 rows x 16 columns]
另一个聚合示例是计算每个组的唯一值的数量。这类似于DataFrameGroupBy.value_counts()
函数,只是它只计算唯一值的数量。
In [88]: ll = [['foo', 1], ['foo', 2], ['foo', 2], ['bar', 1], ['bar', 1]] In [89]: df4 = pd.DataFrame(ll, columns=["A", "B"]) In [90]: df4 Out[90]: A B 0 foo 1 1 foo 2 2 foo 2 3 bar 1 4 bar 1 In [91]: df4.groupby("A")["B"].nunique() Out[91]: A bar 1 foo 2 Name: B, dtype: int64
注意
当as_index=True
时,默认情况下,聚合函数不会将你正在聚合的组作为命名列返回。分组的列将是返回对象的索引。
传递as_index=False
将返回你正在聚合的组作为命名列,无论它们在输入中是命名的索引还是列。
aggregate()
方法
注意
aggregate()
方法可以接受许多不同类型的输入。本节详细介绍了使用字符串别名进行各种 GroupBy 方法的详细信息;其他输入在下面的各节中详细说明。
任何 pandas 实现的缩减方法都可以作为字符串传递给aggregate()
。鼓励用户使用简写agg
。它将操作,就好像调用了相应的方法一样。
In [92]: grouped = df.groupby("A") In [93]: grouped[["C", "D"]].aggregate("sum") Out[93]: C D A bar 0.392940 1.732707 foo -1.796421 2.824590 In [94]: grouped = df.groupby(["A", "B"]) In [95]: grouped.agg("sum") Out[95]: C D A B bar one 0.254161 1.511763 three 0.215897 -0.990582 two -0.077118 1.211526 foo one -0.983776 1.614581 three -0.862495 0.024580 two 0.049851 1.185429
聚合的结果将以组名作为新索引。在多个键的情况下,默认情况下结果是 MultiIndex。如上所述,这可以通过使用as_index
选项来更改:
In [96]: grouped = df.groupby(["A", "B"], as_index=False) In [97]: grouped.agg("sum") Out[97]: A B C D 0 bar one 0.254161 1.511763 1 bar three 0.215897 -0.990582 2 bar two -0.077118 1.211526 3 foo one -0.983776 1.614581 4 foo three -0.862495 0.024580 5 foo two 0.049851 1.185429 In [98]: df.groupby("A", as_index=False)[["C", "D"]].agg("sum") Out[98]: A C D 0 bar 0.392940 1.732707 1 foo -1.796421 2.824590
请注意,您可以使用DataFrame.reset_index()
DataFrame 函数来实现与列名相同的结果,因为列名存储在生成的MultiIndex
中,尽管这将产生额外的副本。
In [99]: df.groupby(["A", "B"]).agg("sum").reset_index() Out[99]: A B C D 0 bar one 0.254161 1.511763 1 bar three 0.215897 -0.990582 2 bar two -0.077118 1.211526 3 foo one -0.983776 1.614581 4 foo three -0.862495 0.024580 5 foo two 0.049851 1.185429
使用用户定义函数进行聚合
用户还可以为自定义聚合提供自己的用户定义函数(UDFs)。
警告
在使用 UDF 进行聚合时,UDF 不应更改提供的Series
。有关更多信息,请参阅使用用户定义函数(UDF)方法进行变异。
注意
使用 UDF 进行聚合通常比在 GroupBy 上使用 pandas 内置方法性能更低。考虑将复杂操作分解为一系列利用内置方法的操作。
In [100]: animals Out[100]: kind height weight 0 cat 9.1 7.9 1 dog 6.0 7.5 2 cat 9.5 9.9 3 dog 34.0 198.0 In [101]: animals.groupby("kind")[["height"]].agg(lambda x: set(x)) Out[101]: height kind cat {9.1, 9.5} dog {34.0, 6.0}
结果的 dtype 将反映聚合函数的 dtype。如果不同组的结果具有不同的 dtype,则将以与DataFrame
构造相同的方式确定公共 dtype。
In [102]: animals.groupby("kind")[["height"]].agg(lambda x: x.astype(int).sum()) Out[102]: height kind cat 18 dog 40
一次应用多个函数
在分组的Series
上,您可以将函数列表或字典传递给SeriesGroupBy.agg()
,输出一个 DataFrame:
In [103]: grouped = df.groupby("A") In [104]: grouped["C"].agg(["sum", "mean", "std"]) Out[104]: sum mean std A bar 0.392940 0.130980 0.181231 foo -1.796421 -0.359284 0.912265
在分组的DataFrame
上,您可以将函数列表传递给DataFrameGroupBy.agg()
以聚合每列,这将产生一个具有分层列索引的聚合结果:
In [105]: grouped[["C", "D"]].agg(["sum", "mean", "std"]) Out[105]: C D sum mean std sum mean std A bar 0.392940 0.130980 0.181231 1.732707 0.577569 1.366330 foo -1.796421 -0.359284 0.912265 2.824590 0.564918 0.884785
结果的聚合以函数本身命名。如果需要重命名,则可以为Series
添加一个链接操作,如下所示:
In [106]: ( .....: grouped["C"] .....: .agg(["sum", "mean", "std"]) .....: .rename(columns={"sum": "foo", "mean": "bar", "std": "baz"}) .....: ) .....: Out[106]: foo bar baz A bar 0.392940 0.130980 0.181231 foo -1.796421 -0.359284 0.912265
对于分组的DataFrame
,您可以以类似的方式重命名:
In [107]: ( .....: grouped[["C", "D"]].agg(["sum", "mean", "std"]).rename( .....: columns={"sum": "foo", "mean": "bar", "std": "baz"} .....: ) .....: ) .....: Out[107]: C D foo bar baz foo bar baz A bar 0.392940 0.130980 0.181231 1.732707 0.577569 1.366330 foo -1.796421 -0.359284 0.912265 2.824590 0.564918 0.884785
注意
一般来说,输出列名应该是唯一的,但 pandas 允许您将相同函数(或具有相同名称的两个函数)应用于同一列。
In [108]: grouped["C"].agg(["sum", "sum"]) Out[108]: sum sum A bar 0.392940 0.392940 foo -1.796421 -1.796421
pandas 还允许您提供多个 lambda 函数。在这种情况下,pandas 将对(无名称)lambda 函数的名称进行修改,对每个后续 lambda 追加_
。
In [109]: grouped["C"].agg([lambda x: x.max() - x.min(), lambda x: x.median() - x.mean()]) Out[109]: <lambda_0> <lambda_1> A bar 0.331279 0.084917 foo 2.337259 -0.215962
命名聚合
为了支持具有对输出列名称的控制的特定列聚合,pandas 接受在DataFrameGroupBy.agg()
和SeriesGroupBy.agg()
中的特殊语法,称为“命名聚合”,其中
- 关键字是输出列名
- 这些值是元组,第一个元素是要选择的列,第二个元素是要应用于该列的聚合。pandas 提供了
NamedAgg
命名元组,字段为['column', 'aggfunc']
,以便更清晰地了解参数是什么。通常,聚合可以是可调用的函数或字符串别名。
In [110]: animals Out[110]: kind height weight 0 cat 9.1 7.9 1 dog 6.0 7.5 2 cat 9.5 9.9 3 dog 34.0 198.0 In [111]: animals.groupby("kind").agg( .....: min_height=pd.NamedAgg(column="height", aggfunc="min"), .....: max_height=pd.NamedAgg(column="height", aggfunc="max"), .....: average_weight=pd.NamedAgg(column="weight", aggfunc="mean"), .....: ) .....: Out[111]: min_height max_height average_weight kind cat 9.1 9.5 8.90 dog 6.0 34.0 102.75
NamedAgg
只是一个namedtuple
。也允许使用普通元组。
In [112]: animals.groupby("kind").agg( .....: min_height=("height", "min"), .....: max_height=("height", "max"), .....: average_weight=("weight", "mean"), .....: ) .....: Out[112]: min_height max_height average_weight kind cat 9.1 9.5 8.90 dog 6.0 34.0 102.75
如果您想要的列名不是有效的 Python 关键字,请构造一个字典并展开关键字参数
In [113]: animals.groupby("kind").agg( .....: **{ .....: "total weight": pd.NamedAgg(column="weight", aggfunc="sum") .....: } .....: ) .....: Out[113]: total weight kind cat 17.8 dog 205.5
在使用命名聚合时,额外的关键字参数不会传递给聚合函数;只有 (column, aggfunc)
对应的键值对应该作为 **kwargs
传递。如果您的聚合函数需要额外的参数,可以使用 functools.partial()
部分应用它们。
命名聚合对于 Series groupby 聚合也是有效的。在这种情况下,没有列选择,因此值只是函数。
In [114]: animals.groupby("kind").height.agg( .....: min_height="min", .....: max_height="max", .....: ) .....: Out[114]: min_height max_height kind cat 9.1 9.5 dog 6.0 34.0
对 DataFrame 列应用不同函数
通过将字典传递给 aggregate
,您可以对 DataFrame 的列应用��同的聚合:
In [115]: grouped.agg({"C": "sum", "D": lambda x: np.std(x, ddof=1)}) Out[115]: C D A bar 0.392940 1.366330 foo -1.796421 0.884785
函数名称也可以是字符串。为了使字符串有效,必须在 GroupBy 上实现它:
In [116]: grouped.agg({"C": "sum", "D": "std"}) Out[116]: C D A bar 0.392940 1.366330 foo -1.796421 0.884785
转换
转换是一个 GroupBy 操作,其结果与被分组的结果索引相同。常见示例包括 cumsum()
和 diff()
。
In [117]: speeds Out[117]: class order max_speed falcon bird Falconiformes 389.0 parrot bird Psittaciformes 24.0 lion mammal Carnivora 80.2 monkey mammal Primates NaN leopard mammal Carnivora 58.0 In [118]: grouped = speeds.groupby("class")["max_speed"] In [119]: grouped.cumsum() Out[119]: falcon 389.0 parrot 413.0 lion 80.2 monkey NaN leopard 138.2 Name: max_speed, dtype: float64 In [120]: grouped.diff() Out[120]: falcon NaN parrot -365.0 lion NaN monkey NaN leopard NaN Name: max_speed, dtype: float64
与聚合不同,用于拆分原始对象的分组不包含在结果中。
注意
由于转换不包括用于拆分结果的分组,因此在 DataFrame.groupby()
和 Series.groupby()
中的参数 as_index
和 sort
没有效果。
转换的常见用途是将结果添加回原始 DataFrame 中。
In [121]: result = speeds.copy() In [122]: result["cumsum"] = grouped.cumsum() In [123]: result["diff"] = grouped.diff() In [124]: result Out[124]: class order max_speed cumsum diff falcon bird Falconiformes 389.0 389.0 NaN parrot bird Psittaciformes 24.0 413.0 -365.0 lion mammal Carnivora 80.2 80.2 NaN monkey mammal Primates NaN NaN NaN leopard mammal Carnivora 58.0 138.2 NaN
Pandas 2.2 中文官方教程和指南(二十·二)(2)https://developer.aliyun.com/article/1508829