In [1]: import pandas as pd
Data used for this tutorial:
  • 本教程使用泰坦尼克号数据集,存储为CSV格式。数据包括以下数据列:

    • PassengerId: 每位乘客的ID。

    • 幸存者:乘客是否幸存的指示。0 表示是,1 表示否。

    • Pclass:三种票等级之一:等级 1、等级 2 和等级 3

    • 名称:乘客的姓名。

    • Sex: 乘客的性别。

    • 年龄:乘客的年龄(岁)。

    • SibSp: 船上兄弟姐妹或配偶的数量。

    • Parch: 父母或孩子在船上的数量。

    • 票:乘客的票号。

    • 票价:指示票价。

    • Cabin: 乘客的舱位号。

    • Embarked: 登船港口。

    To raw data
    In [2]: titanic = pd.read_csv("data/titanic.csv")
    
    In [3]: titanic.head()
    Out[3]: 
       PassengerId  Survived  Pclass                                               Name     Sex   Age  SibSp  Parch            Ticket     Fare Cabin Embarked
    0            1         0       3                            Braund, Mr. Owen Harris    male  22.0      1      0         A/5 21171   7.2500   NaN        S
    1            2         1       1  Cumings, Mrs. John Bradley (Florence Briggs Th...  female  38.0      1      0          PC 17599  71.2833   C85        C
    2            3         1       3                              Heikkinen, Miss Laina  female  26.0      0      0  STON/O2. 3101282   7.9250   NaN        S
    3            4         1       1       Futrelle, Mrs. Jacques Heath (Lily May Peel)  female  35.0      1      0            113803  53.1000  C123        S
    4            5         0       3                           Allen, Mr. William Henry    male  35.0      0      0            373450   8.0500   NaN        S
    

如何计算汇总统计#

聚合统计数据#

../../_images/06_aggregate.svg
  • 泰坦尼克号乘客的平均年龄是多少?

    In [4]: titanic["Age"].mean()
    Out[4]: 29.69911764705882
    

不同的统计数据是可用的,并且可以应用于具有数值数据的列。通常,操作会排除缺失数据,并默认在行之间进行操作。

../../_images/06_reduction.svg
  • 泰坦尼克号乘客的中位年龄和票价是多少?

    In [5]: titanic[["Age", "Fare"]].median()
    Out[5]: 
    Age     28.0000
    Fare    14.4542
    dtype: float64
    

    应用于 DataFrame 多个列的统计(选择两列返回一个 DataFrame,参见 子集数据教程)是为每个数值列计算的。

聚合统计可以同时为多个列计算。还记得 第一个教程 中的 describe 函数吗?

In [6]: titanic[["Age", "Fare"]].describe()
Out[6]: 
              Age        Fare
count  714.000000  891.000000
mean    29.699118   32.204208
std     14.526497   49.693429
min      0.420000    0.000000
25%     20.125000    7.910400
50%     28.000000   14.454200
75%     38.000000   31.000000
max     80.000000  512.329200

可以使用 DataFrame.agg() 方法定义给定列的聚合统计的特定组合,而不是预定义的统计数据:

In [7]: titanic.agg(
   ...:     {
   ...:         "Age": ["min", "max", "median", "skew"],
   ...:         "Fare": ["min", "max", "median", "mean"],
   ...:     }
   ...: )
   ...: 
Out[7]: 
              Age        Fare
min      0.420000    0.000000
max     80.000000  512.329200
median  28.000000   14.454200
skew     0.389108         NaN
mean          NaN   32.204208
To user guide

描述性统计的详细信息在用户指南的 描述性统计 部分提供。

按类别分组的聚合统计数据#

../../_images/06_groupby.svg
  • 男性与女性泰坦尼克号乘客的平均年龄是多少?

    In [8]: titanic[["Sex", "Age"]].groupby("Sex").mean()
    Out[8]: 
                  Age
    Sex              
    female  27.915709
    male    30.726645
    

    由于我们的兴趣是每个性别的平均年龄,首先对这两列进行子选择:titanic[["Sex", "Age"]]。接下来,在 Sex 列上应用 groupby() 方法,按类别分组。计算并返回 每个性别 的平均年龄。

计算给定的统计量(例如 mean 年龄)*对于列中的每个类别*(例如 Sex 列中的男性/女性)是一种常见模式。groupby 方法用于支持这种类型的操作。这符合更一般的 split-apply-combine 模式:

  • 分割 数据为组

  • 应用 一个函数到每个独立的分组

  • Combine 将结果合并到一个数据结构中

应用和合并步骤通常在 pandas 中一起完成。

在之前的例子中,我们明确地先选择了两列。如果没有选择,通过传递 numeric_only=Truemean 方法会应用到每一列包含数值的列上:

In [9]: titanic.groupby("Sex").mean(numeric_only=True)
Out[9]: 
        PassengerId  Survived    Pclass        Age     SibSp     Parch       Fare
Sex                                                                              
female   431.028662  0.742038  2.159236  27.915709  0.694268  0.649682  44.479818
male     454.147314  0.188908  2.389948  30.726645  0.429809  0.235702  25.523893

获取 Pclass 的平均值没有太大意义。如果我们只对每个性别的平均年龄感兴趣,分组数据上的列选择(方括号 [] 如常)也是支持的:

In [10]: titanic.groupby("Sex")["Age"].mean()
Out[10]: 
Sex
female    27.915709
male      30.726645
Name: Age, dtype: float64
../../_images/06_groupby_select_detail.svg

备注

Pclass 列包含数值数据,但实际上代表3个类别(或因子),分别带有标签‘1’、‘2’和‘3’。对这些数据进行统计计算没有太大意义。因此,pandas 提供了 Categorical 数据类型来处理这种类型的数据。更多信息请参见用户指南 分类数据 部分。

  • 每种性别和客舱等级组合的平均票价是多少?

    In [11]: titanic.groupby(["Sex", "Pclass"])["Fare"].mean()
    Out[11]: 
    Sex     Pclass
    female  1         106.125798
            2          21.970121
            3          16.118810
    male    1          67.226127
            2          19.741782
            3          12.661633
    Name: Fare, dtype: float64
    

    可以通过多列同时进行分组。将列名作为列表提供给 groupby() 方法。

To user guide

关于拆分-应用-合并方法的完整描述在用户指南的 分组操作 部分提供。

按类别统计记录数#

../../_images/06_valuecounts.svg
  • 每个舱位的乘客人数是多少?

    In [12]: titanic["Pclass"].value_counts()
    Out[12]: 
    Pclass
    3    491
    1    216
    2    184
    Name: count, dtype: int64
    

    value_counts() 方法计算列中每个类别的记录数。

这个函数是一个快捷方式,它实际上是一个结合了计算每个组内记录数量的分组操作:

In [13]: titanic.groupby("Pclass")["Pclass"].count()
Out[13]: 
Pclass
1    216
2    184
3    491
Name: Pclass, dtype: int64

备注

sizecount 都可以与 groupby 结合使用。虽然 size 包括 NaN 值并仅提供行数(表的大小),但 count 排除了缺失值。在 value_counts 方法中,使用 dropna 参数来包括或排除 NaN 值。

To user guide

用户指南在 value_counts 上有一个专门的章节,请参见 离散化 页面。

REMEMBER

  • 聚合统计可以计算在整个列或行上。

  • groupby 提供了 分割-应用-合并 模式的能力。

  • value_counts 是一个方便的快捷方式,用于计算变量每个类别中的条目数。

To user guide

关于拆分-应用-合并方法的完整描述在用户指南页面中关于 分组操作 的部分提供。