掌握 Pandas:提升你的数据分析效率 – wiki词典


掌握 Pandas:提升你的数据分析效率

在当今数据驱动的世界中,数据分析已成为一项核心技能。无论您是数据科学家、分析师还是任何需要从数据中获取洞察的专业人士,掌握正确的工具都至关重要。Python 的 Pandas 库正是这样一款强大的工具,它以其直观的数据结构和高性能的数据操作能力,彻底改变了我们处理和分析结构化数据的方式。

本文将深入探讨 Pandas 的核心功能、关键操作以及一些提升效率的技巧,帮助您从数据中提取更多价值。

什么是 Pandas?为什么它如此重要?

Pandas 是一个开源的 Python 库,为数据操作和分析提供高性能、易于使用的数据结构。它的名称来源于“Panel Data”(面板数据)和“Python Data Analysis”的缩写。

Pandas 的核心优势在于:

  1. 直观的数据结构:提供 Series(一维)和 DataFrame(二维)两种核心数据结构,它们与电子表格或 SQL 表非常相似,使得数据的表示和理解变得简单。
  2. 强大的数据操作能力:无论是数据清洗、转换、筛选、聚合还是合并,Pandas 都提供了高效且灵活的函数。
  3. 与科学计算生态系统集成:与 NumPy、SciPy、Matplotlib 等其他 Python 科学计算库无缝协作,构建完整的数据分析工作流。
  4. 处理多种数据格式:可以轻松读取和写入 CSV、Excel、SQL 数据库、JSON 等多种格式的数据。

Pandas 的核心数据结构

理解 Series 和 DataFrame 是掌握 Pandas 的基石。

1. Series (序列)

Series 是一种带标签的一维数组,可以容纳任何数据类型(整数、字符串、浮点数、Python 对象等)。它由两部分组成:数据和与之关联的标签(索引)。

“`python
import pandas as pd

从列表创建 Series

s = pd.Series([1, 3, 5, 7, 9])
print(s)

0 1

1 3

2 5

3 7

4 9

dtype: int64

从字典创建 Series,键将作为索引

s_dict = pd.Series({‘a’: 10, ‘b’: 20, ‘c’: 30})
print(s_dict)

a 10

b 20

c 30

dtype: int64

“`

2. DataFrame (数据框)

DataFrame 是一个二维的、大小可变的、表格型数据结构,包含带有标签的列(可以有不同类型)。您可以将其视为一个电子表格、SQL 表或一个 Series 对象的字典。它是 Pandas 最常用的对象。

“`python

从字典创建 DataFrame

data = {
‘Name’: [‘Alice’, ‘Bob’, ‘Charlie’, ‘David’],
‘Age’: [25, 30, 35, 40],
‘City’: [‘New York’, ‘Paris’, ‘London’, ‘Tokyo’]
}
df = pd.DataFrame(data)
print(df)

Name Age City

0 Alice 25 New York

1 Bob 30 Paris

2 Charlie 35 London

3 David 40 Tokyo

“`

核心数据操作与效率提升

掌握以下操作是高效使用 Pandas 的关键。

1. 数据加载与查看

  • 读取数据:Pandas 提供了 read_csv(), read_excel(), read_sql(), read_json() 等函数来加载各种数据源。
    python
    df_csv = pd.read_csv('your_data.csv')
    df_excel = pd.read_excel('your_data.xlsx', sheet_name='Sheet1')

    效率提示:对于大型 CSV 文件,使用 nrows 参数只读取部分行,或者使用 chunksize 参数进行分块读取,以减少内存占用。usecols 可以指定只读取需要的列。
  • 初步查看
    • df.head(n) / df.tail(n):查看前/后 N 行数据。
    • df.info():提供 DataFrame 的简洁摘要,包括索引类型、列类型、非空值数量和内存使用情况。
    • df.describe():生成描述性统计数据,概括数值型列的中心趋势、离散程度和分布情况。
    • df.shape:获取 DataFrame 的行数和列数。
    • df.columns:获取所有列名。
    • df.index:获取索引。

2. 数据选择与筛选

  • 列选择:通过列名选择一列或多列。
    python
    names = df['Name'] # 选择单列,返回 Series
    subset = df[['Name', 'Age']] # 选择多列,返回 DataFrame
  • 行选择
    • .loc[] (基于标签):用于通过行/列标签选择数据。
      python
      row_0 = df.loc[0] # 选择索引为 0 的行
      cell = df.loc[0, 'Name'] # 选择特定单元格
      subset_rows = df.loc[0:2, ['Name', 'City']] # 选择多行多列
    • .iloc[] (基于整数位置):用于通过行/列的整数位置(从 0 开始)选择数据。
      python
      row_0_iloc = df.iloc[0]
      cell_iloc = df.iloc[0, 0]
      subset_rows_iloc = df.iloc[0:3, [0, 2]]
  • 条件筛选:根据条件过滤行。
    python
    older_than_30 = df[df['Age'] > 30]
    new_yorkers = df[(df['City'] == 'New York') & (df['Age'] < 30)] # 多个条件

    效率提示:尽量使用 NumPy 数组操作和矢量化函数进行条件筛选,避免使用循环。

3. 处理缺失数据

  • df.isnull() / df.notnull():返回布尔型 DataFrame,指示每个位置是否为缺失值(NaN)。
  • df.dropna():删除含有缺失值的行或列。
    python
    df_cleaned = df.dropna() # 删除任何含 NaN 的行
    df_cleaned_col = df.dropna(axis=1) # 删除任何含 NaN 的列
    df_subset_cleaned = df.dropna(subset=['Age', 'City']) # 只考虑特定列
  • df.fillna(value):用指定的值填充缺失值。
    python
    df_filled_age = df['Age'].fillna(df['Age'].mean()) # 用均值填充 Age 列
    df_filled_zero = df.fillna(0) # 用 0 填充所有 NaN
    df_filled_ffill = df.fillna(method='ffill') # 使用前一个有效值填充

    效率提示inplace=True 参数可以直接修改 DataFrame,避免创建副本,节省内存,但需谨慎使用。

4. 数据分组与聚合 (groupby())

groupby() 是 Pandas 中最强大的功能之一,用于按一个或多个键对数据进行分组,然后对每个组独立应用聚合函数(如 sum(), mean(), count(), min(), max())。

“`python

假设我们有一个包含部门和薪水的数据

data_hr = {
‘Department’: [‘HR’, ‘IT’, ‘HR’, ‘IT’, ‘Sales’, ‘Sales’],
‘Salary’: [50000, 70000, 60000, 80000, 90000, 75000]
}
df_hr = pd.DataFrame(data_hr)

按部门分组并计算平均薪水

avg_salary_by_dept = df_hr.groupby(‘Department’)[‘Salary’].mean()
print(avg_salary_by_dept)

Department

HR 55000.0

IT 75000.0

Sales 82500.0

Name: Salary, dtype: float64

多个聚合函数

agg_data = df_hr.groupby(‘Department’).agg(
Avg_Salary=(‘Salary’, ‘mean’),
Max_Salary=(‘Salary’, ‘max’),
Count=(‘Salary’, ‘count’)
)
print(agg_data)

Avg_Salary Max_Salary Count

Department

HR 55000.0 60000 2

IT 75000.0 80000 2

Sales 82500.0 90000 2

``
**效率提示**:对于大型数据集,
groupby()` 操作通常比显式循环更高效。

5. 数据合并 (merge(), concat())

  • pd.merge() (连接/联结):类似于 SQL 的 JOIN 操作,根据一个或多个键合并 DataFrame。
    “`python
    df1 = pd.DataFrame({‘ID’: [1, 2, 3], ‘Value1’: [‘A’, ‘B’, ‘C’]})
    df2 = pd.DataFrame({‘ID’: [2, 3, 4], ‘Value2’: [‘X’, ‘Y’, ‘Z’]})

    merged_df = pd.merge(df1, df2, on=’ID’, how=’inner’) # 内连接

    ID Value1 Value2

    0 2 B X

    1 3 C Y

    * **`pd.concat()` (拼接)**:用于沿特定轴堆叠 Series 或 DataFrame。python
    df_top = pd.DataFrame({‘A’: [1, 2], ‘B’: [3, 4]})
    df_bottom = pd.DataFrame({‘A’: [5, 6], ‘B’: [7, 8]})
    concatenated_df = pd.concat([df_top, df_bottom]) # 默认按行拼接

    A B

    0 1 3

    1 2 4

    0 5 7

    1 6 8

    ``
    **效率提示**:对于大型合并操作,确保合并键的
    dtype` 相同可以提高效率。

6. 应用函数 (apply(), map(), applymap())

  • df.apply()
    • 应用于 Series 时,对 Series 中的每个元素执行函数。
    • 应用于 DataFrame 时,对行或列执行函数。
      python
      df['Age_squared'] = df['Age'].apply(lambda x: x**2) # 对 Age 列的每个元素平方
  • Series.map():仅用于 Series,将一个函数或字典映射到 Series 的每个元素。
    python
    city_mapping = {'New York': 'USA', 'Paris': 'France', 'London': 'UK', 'Tokyo': 'Japan'}
    df['Country'] = df['City'].map(city_mapping)
  • df.applymap():仅用于 DataFrame,对 DataFrame 的每个 元素 执行函数。
    python
    # 假设需要对所有数值进行格式化
    df_num = pd.DataFrame({'Col1': [1.234, 2.345], 'Col2': [3.456, 4.567]})
    df_formatted = df_num.applymap(lambda x: f"{x:.2f}")

    效率提示:尽可能使用矢量化操作(如 df['col'] * 2)而不是 apply() 系列函数,因为矢量化操作通常更快。只有当没有直接的矢量化替代方案时,才考虑 apply()

7. 时间序列功能

Pandas 在处理日期和时间数据方面表现出色。

  • 转换日期时间pd.to_datetime()
    python
    dates = pd.Series(['2023-01-01', '2023-01-02', '2023-01-03'])
    df['Date'] = pd.to_datetime(dates)
  • 时间戳操作:提取年份、月份、日期、星期几等。
    python
    df['Year'] = df['Date'].dt.year
    df['Month'] = df['Date'].dt.month
  • 重采样 (resample()):用于时间序列数据的频率转换和聚合。
    python
    # 假设 df 有一个日期时间索引
    # df.set_index('Date', inplace=True)
    # daily_data.resample('W').mean() # 按周平均

提升 Pandas 效率的通用技巧

  1. 使用矢量化操作:尽可能利用 Pandas 和 NumPy 的内置函数,它们在 C 语言层面实现,速度远快于 Python 循环。
  2. 避免 for 循环:除非绝对必要,否则应避免在 DataFrame 或 Series 上进行显式循环。
  3. 选择合适的数据类型 (dtype):使用 df.info() 检查数据类型。如果可能,将数值列转换为更小的整数或浮点类型,将字符串列转换为 category 类型(如果唯一值数量有限),可以显著减少内存使用并提高操作速度。
    python
    df['Category_Col'] = df['Category_Col'].astype('category')
  4. 利用 inplace=True:在修改 DataFrame 的函数中使用 inplace=True 可以避免创建新的 DataFrame 对象,从而节省内存。但缺点是它不会返回新的 DataFrame,且链式操作可能变得复杂。
  5. 分块处理大数据:对于内存无法一次性加载的大文件,使用 pd.read_csv(..., chunksize=N) 分块读取和处理数据。
  6. 优化数据读取
    • 使用 nrowsusecols 参数在读取时过滤不必要的数据。
    • 指定 dtype 参数,避免 Pandas 自动推断数据类型,特别是在有混合类型列时。
  7. 善用索引:正确设置和使用索引可以加速数据查找和合并操作。对于经常用于筛选的列,考虑将其设为索引。

结语

Pandas 是数据分析师的瑞士军刀。通过熟练掌握其核心数据结构和操作,并结合本文介绍的效率提升技巧,您将能够更快速、更有效地处理、清洗和分析数据,从而更快地获得有价值的洞察。数据分析的旅程是持续学习和实践的过程,不断探索 Pandas 的高级功能,将使您在数据科学领域游刃有余。


滚动至顶部