Pandas DataFrame常用操作:筛选、排序、分组、聚合

Pandas DataFrame:筛选、排序、分组与聚合的全面指南

Pandas 是 Python 数据分析领域最受欢迎的库之一,其核心数据结构 DataFrame 为处理结构化数据提供了强大的工具。DataFrame 类似于一个二维表格,可以容纳各种类型的数据,并提供了丰富的操作方法。本文将深入探讨 DataFrame 的核心操作:数据筛选、排序、分组和聚合,并通过大量示例帮助您掌握这些关键技能。

一、 数据筛选:精准定位目标数据

数据筛选是数据分析的第一步,它可以帮助我们从庞大的数据集中提取出感兴趣的部分。Pandas DataFrame 提供了多种灵活的筛选方法,满足各种场景的需求。

1.1 基于列的筛选

  • 选择单列: 使用方括号 [] 或点运算符 . 可以选择 DataFrame 中的单个列。返回的结果是一个 Pandas Series。

    ```python
    import pandas as pd

    data = {'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Emily'],
    'Age': [25, 30, 28, 22, 27],
    'City': ['New York', 'London', 'Paris', 'Tokyo', 'Sydney']}
    df = pd.DataFrame(data)

    使用方括号

    ages = df['Age']
    print(ages)

    使用点运算符 (列名中不能有空格或其他特殊字符)

    names = df.Name
    print(names)
    ```

  • 选择多列: 使用包含列名列表的方括号 [] 可以选择 DataFrame 中的多个列。返回的结果是一个新的 DataFrame。

    ```python

    选择 Name 和 City 两列

    name_city = df[['Name', 'City']]
    print(name_city)
    ```

1.2 基于行的筛选

  • lociloc 这是 Pandas 中最常用的两种行筛选方法。

    • loc 基于行标签(索引)进行筛选。
    • iloc 基于行位置(整数索引)进行筛选。

    ```python

    使用 loc 选择索引为 2 的行

    row_2 = df.loc[2]
    print(row_2)

    使用 iloc 选择第 3 行 (索引从 0 开始)

    row_3 = df.iloc[2]
    print(row_3)

    选择多行

    rows_0_to_2 = df.loc[0:2] # 包括索引为 2 的行
    print(rows_0_to_2)

    rows_1_and_3 = df.iloc[[1, 3]] # 选择第 2 行和第 4 行
    print(rows_1_and_3)

    loc 和 iloc 也可以同时选择行和列

    选择索引为 1 的行的 Name 列

    name_row_1 = df.loc[1, 'Name']
    print(name_row_1)

    选择第 2 行的第 1 列 (Age 列)

    age_row_2 = df.iloc[1, 0] # 注意: 列索引也是从0开始
    print(age_row_2)
    ``
    * **
    head()tail()`**: 用于查看开头或者结尾几行的数据,默认查看5行。

    python
    print(df.head()) #查看前5行
    print(df.tail(3)) #查看后3行

1.3 基于条件的筛选 (布尔索引)

这是 Pandas 筛选数据最强大、最灵活的方式。它使用布尔条件(True/False)来选择满足条件的行。

  • 单个条件:

    ```python

    选择年龄大于 25 的行

    older_than_25 = df[df['Age'] > 25]
    print(older_than_25)

    选择城市为 New York 的行

    new_yorkers = df[df['City'] == 'New York']
    print(new_yorkers)
    ```

  • 多个条件:

    • 使用 & (与) 连接多个条件。
    • 使用 | (或) 连接多个条件。
    • 使用 ~ (非) 对条件取反。
    • 注意: 每个条件都必须用圆括号 () 括起来。

    ```python

    选择年龄大于 25 且城市为 New York 的行

    older_new_yorkers = df[(df['Age'] > 25) & (df['City'] == 'New York')]
    print(older_new_yorkers)

    选择年龄小于 25 或城市为 London 的行

    young_or_londoners = df[(df['Age'] < 25) | (df['City'] == 'London')]
    print(young_or_londoners)

    选择城市不是 Tokyo 的行

    not_tokyo = df[~(df['City'] == 'Tokyo')]
    print(not_tokyo)
    ```

  • isin() 方法: 用于判断 DataFrame 中的值是否在给定的列表中。

    ```python

    选择城市为 New York 或 London 的行

    ny_or_london = df[df['City'].isin(['New York', 'London'])]
    print(ny_or_london)
    ``
    * **
    between()`方法:** 用于判断某列的值是否在指定的范围内(包含边界值)

    ```python

    选择年龄在25到30岁之间的人

    age_between = df[df['Age'].between(25,30)]
    print(age_between)
    ```

  • str 属性: 对于包含字符串的列,可以使用 str 属性提供的字符串方法进行筛选。

    ```python

    选择名字以 'A' 开头的行

    starts_with_A = df[df['Name'].str.startswith('A')]
    print(starts_with_A)

    选择城市名包含 'o' 的行

    contains_o = df[df['City'].str.contains('o')]
    print(contains_o)
    ```

  • query() 方法: 允许使用类似 SQL 的语法进行条件筛选。

    ```python

    选择年龄大于 25 且城市为 New York 的行

    result = df.query("Age > 25 and City == 'New York'")
    print(result)
    # 使用变量
    min_age = 25
    result2 = df.query("Age > @min_age")
    print(result2)
    ```

二、 数据排序:理清数据脉络

排序可以帮助我们按照特定的顺序组织数据,更方便地观察数据的分布和趋势。

2.1 sort_values() 方法

  • 按单列排序:

    ```python

    按年龄升序排序

    df_sorted_age = df.sort_values('Age')
    print(df_sorted_age)

    按年龄降序排序

    df_sorted_age_desc = df.sort_values('Age', ascending=False)
    print(df_sorted_age_desc)
    ```

  • 按多列排序:

    ```python

    先按城市升序排序,再按年龄降序排序

    df_sorted_multi = df.sort_values(['City', 'Age'], ascending=[True, False])
    print(df_sorted_multi)
    ``
    * **
    inplace`参数:**

    python
    # 默认情况下, sort_values() 不会修改原始 DataFrame, 而是返回一个新的 DataFrame
    # 如果要直接修改原始 DataFrame, 可以设置 inplace=True
    df.sort_values('Age', inplace=True)
    print(df) #此时df已被排序

    2.2 sort_index() 方法

    • 按行索引排序

    ```python
    #打乱索引
    df2 = df.sample(frac=1)
    print(df2)

    按索引升序排序

    print(df2.sort_index())

    按索引降序排序

    print(df2.sort_index(ascending=False))
    ```

    三、 数据分组:洞察数据特征

分组是将数据按照某个或某些特征划分成不同的组,然后对每个组进行独立分析的过程。Pandas 提供了强大的 groupby() 方法来实现数据分组。

3.1 groupby() 方法

  • 基本用法:

    ```python

    按城市分组

    grouped_by_city = df.groupby('City')
    print(grouped_by_city) # 返回一个 DataFrameGroupBy 对象,它本身并不包含数据
    ```
    DataFrameGroupBy 对象是一个中间对象,它包含了分组的信息,但并没有进行实际的计算。 要查看分组后的结果,需要对 DataFrameGroupBy 对象应用聚合函数。

  • 分组后应用聚合函数:

    • mean(): 计算平均值。
    • sum(): 计算总和。
    • count(): 计算数量。
    • min(): 计算最小值。
    • max(): 计算最大值。
    • std(): 计算标准差。
    • var(): 计算方差。
      ...等等

    ```python

    计算每个城市的平均年龄

    average_age_by_city = grouped_by_city['Age'].mean()
    print(average_age_by_city)

    计算每个城市的人数

    count_by_city = grouped_by_city.size() # size() 可以计算每个分组的大小
    print(count_by_city)

    或者使用

    count_by_city = grouped_by_city['Name'].count()
    print(count_by_city)

    计算每个城市的年龄总和、最小值和最大值

    stats_by_city = grouped_by_city['Age'].agg(['sum', 'min', 'max'])
    print(stats_by_city)
    ```

  • 按多列分组:

    ```python

    添加一列 'Gender'

    df['Gender'] = ['Female', 'Male', 'Male', 'Male', 'Female']

    按城市和性别分组

    grouped_by_city_gender = df.groupby(['City', 'Gender'])

    计算每个城市、每个性别的平均年龄

    average_age_by_city_gender = grouped_by_city_gender['Age'].mean()
    print(average_age_by_city_gender)
    ```

    3.2 遍历分组

    • 你可以像遍历字典一样遍历DataFrameGroupBy对象

    python
    for name, group in grouped_by_city:
    print(f"Group Name: {name}")
    print(group)
    print("-" * 20)

3.3 get_group()方法

  • 可以使用get_group()方法获取特定分组的数据

    python
    london_group = grouped_by_city.get_group('London')
    print(london_group)

四、 数据聚合:提炼数据精华

聚合是在分组的基础上,对每个组的数据进行统计计算,得到汇总结果的过程。前面在介绍 groupby() 方法时已经介绍了常用的聚合函数。这里介绍更高级的聚合方法。

4.1 agg() 方法 (aggregate)

agg() 方法允许您对每个组应用一个或多个聚合函数。

  • 对不同的列应用不同的聚合函数:

    ```python

    按城市分组,计算每个城市的平均年龄和最大年龄

    result = df.groupby('City').agg({'Age': ['mean', 'max']})
    print(result)

    按城市分组,计算每个城市的平均年龄,以及人数

    result = df.groupby('City').agg({'Age': 'mean', 'Name': 'count'})
    print(result)
    ```

  • 自定义聚合函数:

    ```python

    定义一个函数,计算数据的范围 (最大值 - 最小值)

    def data_range(series):
    return series.max() - series.min()

    按城市分组,计算每个城市的年龄范围

    age_range_by_city = df.groupby('City')['Age'].agg(data_range)
    print(age_range_by_city)

    # 也可以使用 lambda 表达式
    age_range_by_city = df.groupby('City')['Age'].agg(lambda x: x.max() - x.min())
    print(age_range_by_city)
    ```

    4.2 transform()方法

    transform()方法会将聚合结果应用到原始DataFrame的每一行。 它并不会改变原始 DataFrame 的形状。

python
# 按城市分组,计算每个城市的平均年龄, 并将结果添加到原始DataFrame中
df['Average_Age_By_City'] = df.groupby('City')['Age'].transform('mean')
print(df)

4.3 apply()方法

apply()方法更加灵活, 它可以对每个分组应用更复杂的自定义函数, 这些函数甚至可以返回一个新的DataFrame。

```python

定义一个函数,对每个分组的数据进行排序并选择前两行

def top_n(group, n=2):
return group.sort_values('Age', ascending=False).head(n)

# 按城市分组,应用 top_n 函数
top_2_by_city = df.groupby('City').apply(top_n)
print(top_2_by_city)
```

总结

本文详细介绍了 Pandas DataFrame 的筛选、排序、分组和聚合操作。这些操作是数据分析的核心技能,掌握它们可以帮助您高效地处理和分析各种结构化数据。

  • 数据筛选: 灵活运用基于列、行和条件的筛选方法,精准定位目标数据。
  • 数据排序: 使用 sort_values()sort_index() 方法对数据进行排序,理清数据脉络。
  • 数据分组: 使用 groupby() 方法将数据分组,结合聚合函数洞察数据特征。
  • 数据聚合: 使用 agg()transform()apply() 方法进行更高级的聚合,提炼数据精华。

希望本文能帮助您深入理解 Pandas DataFrame 的核心操作。在实际应用中,您可以根据具体需求灵活组合这些操作,实现更复杂的数据分析任务。 建议您在学习过程中多动手实践,通过实际操作加深理解和记忆。

THE END