Pandas 2.2 中文官方教程和指南(二十·二)(1)

简介: Pandas 2.2 中文官方教程和指南(二十·二)

通过组进行迭代

有了 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_indexsort 没有效果。

转换的常见用途是将结果添加回原始 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

相关文章
|
1月前
|
存储 JSON 数据格式
Pandas 使用教程 CSV - CSV 转 JSON
Pandas 使用教程 CSV - CSV 转 JSON
20 0
|
1月前
|
JSON 数据格式 Python
Pandas 使用教程 JSON
Pandas 使用教程 JSON
25 0
|
1月前
|
SQL 数据采集 JSON
Pandas 使用教程 Series、DataFrame
Pandas 使用教程 Series、DataFrame
33 0
|
3月前
|
数据采集 存储 数据可视化
Pandas高级教程:数据清洗、转换与分析
Pandas是Python的数据分析库,提供Series和DataFrame数据结构及数据分析工具,便于数据清洗、转换和分析。本教程涵盖Pandas在数据清洗(如缺失值、重复值和异常值处理)、转换(数据类型转换和重塑)和分析(如描述性统计、分组聚合和可视化)的应用。通过学习Pandas,用户能更高效地处理和理解数据,为数据分析任务打下基础。
231 3
|
4月前
|
索引 Python
Pandas 2.2 中文官方教程和指南(一)(4)
Pandas 2.2 中文官方教程和指南(一)
44 0
|
4月前
|
存储 SQL JSON
Pandas 2.2 中文官方教程和指南(一)(3)
Pandas 2.2 中文官方教程和指南(一)
61 0
|
4月前
|
XML 关系型数据库 PostgreSQL
Pandas 2.2 中文官方教程和指南(一)(2)
Pandas 2.2 中文官方教程和指南(一)
110 0
|
4月前
|
XML 关系型数据库 MySQL
Pandas 2.2 中文官方教程和指南(一)(1)
Pandas 2.2 中文官方教程和指南(一)
123 0
|
4月前
|
C++ 索引 Python
Pandas 2.2 中文官方教程和指南(五)(4)
Pandas 2.2 中文官方教程和指南(五)
37 0
|
4月前
|
索引 Python
Pandas 2.2 中文官方教程和指南(五)(3)
Pandas 2.2 中文官方教程和指南(五)
36 0