Python数据分析库指南:NumPy与Pandas

目录


NumPy库的功能与作用

核心功能

  1. 多维数组对象 (ndarray)
  2. 高效的N维数组容器
  3. 支持向量化运算

  4. 快速的数值计算

  5. 基于C语言实现的高性能运算
  6. 避免Python循环开销

  7. 广播机制

  8. 不同形状数组间的智能运算
  9. 自动扩展维度进行计算

主要特点

import numpy as np

# 创建数组
arr = np.array([1, 2, 3, 4, 5])
matrix = np.array([[1, 2, 3], [4, 5, 6]])

# 向量化运算
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
result = a + b  # [5, 7, 9]

# 广播机制
a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([10, 20, 30])
result = a + b  # b被广播到与a相同的形状

应用场景

  • 科学计算基础
  • 图像处理
  • 信号处理
  • 物理模拟
  • 金融分析

Pandas库的功能与作用

核心数据结构

  1. Series - 一维带标签数组
  2. DataFrame - 二维表格数据结构

主要功能模块

1. 数据读取和写入

import pandas as pd

# 读取各种格式
df_csv = pd.read_csv('file.csv')
df_excel = pd.read_excel('file.xlsx')
df_json = pd.read_json('file.json')

# 写入数据
df.to_csv('output.csv', index=False)
df.to_excel('output.xlsx', index=False)

2. 数据查看和基本信息

df.head()           # 前5行
df.tail()           # 后5行
df.shape            # 维度
df.columns          # 列名
df.info()           # 详细信息
df.describe()       # 统计描述

3. 数据清洗

# 处理缺失值
df.dropna()                    # 删除缺失值
df.fillna(0)                   # 填充缺失值
df.fillna(method='ffill')      # 前向填充

# 处理重复值
df.drop_duplicates()           # 删除重复行

4. 数据选择和索引

# 基于标签的选择
df.loc[0]                      # 按索引标签
df.loc[0:5]                    # 切片
df.loc[df['col'] > 0.5]        # 布尔索引

# 基于位置的选择
df.iloc[0]                     # 第一行
df.iloc[0:5]                   # 前5行

# 布尔索引
df[(df['age'] > 30) & (df['city'] == 'Beijing')]

5. 数据分组和聚合

# 分组操作
grouped = df.groupby('category')
result = grouped.agg({'col1': 'sum', 'col2': 'mean'})

# 常用聚合函数
grouped.sum()
grouped.mean()
grouped.count()
grouped.std()

6. 数据合并和连接

# 合并操作
pd.concat([df1, df2])                    # 轴向连接
pd.merge(df1, df2, on='key')             # 数据库风格连接
df1.join(df2, how='inner')               # 索引连接

7. 数据重塑和透视

# 透视表
pivot = pd.pivot_table(df, 
                      values='value',
                      index='date',
                      columns='category',
                      aggfunc='sum')

# melt - 宽表转长表
melted = pd.melt(df, 
                id_vars=['id'],
                value_vars=['col1', 'col2'])

实际应用场景

  • 数据清洗和预处理
  • 数据分析和报告
  • 金融分析
  • 商业智能
  • 机器学习特征工程

DataFrame操作指南

显示特定行数据

# 使用loc按标签索引
print(df.loc['row_label'])

# 使用iloc按位置索引
print(df.iloc[0])           # 第一行
print(df.iloc[-1])          # 最后一行

# 使用布尔索引
print(df[df['age'] > 30])

# 使用query方法
print(df.query("age > 30 and city == 'Beijing'"))

列操作

# 选择列
df['column_name']           # 选择单列
df[['col1', 'col2']]        # 选择多列

# 删除列
df.drop('column', axis=1)    # 删除单列
df.drop(['col1', 'col2'], axis=1)  # 删除多列

# 使用del关键字
del df['column']

# 使用pop方法(删除并返回)
column_data = df.pop('column')

行操作

# 删除行
df.drop([0, 1])              # 删除索引为0和1的行

# 条件删除
df = df[df['age'] >= 18]     # 保留年龄大于等于18的行

计算新列

# 计算价格波动幅度
df['price_range_pct'] = (df['high'] - df['low']) / df['open'] * 100

# 计算最大值
df['max_value'] = df[['open', 'high', 'close']].max(axis=1)

# 使用apply函数
df['new_col'] = df.apply(lambda row: row['col1'] + row['col2'], axis=1)

日期处理

# 日期比较的正确方法
import pandas as pd
import datetime

# 错误方法:类型不匹配
# df[df['date'] >= datetime.date(2025,1,1)]  # 会报错

# 正确方法
df[df['date'] >= '2025-01-01']                    # 使用字符串
df[df['date'] >= pd.Timestamp('2025-01-01')]      # 使用Timestamp
df[df['date'] >= pd.Timestamp(datetime.date(2025,1,1))]  # 转换后使用

# 日期范围查询
df[df['date'].between('2025-01-01', '2025-03-31')]
df[(df['date'] >= '2025-01-01') & (df['date'] <= '2025-03-31')]

Series操作指南

创建Series

# 从列表创建
s1 = pd.Series([1, 3, 5, np.nan, 6, 8])

# 从字典创建
s2 = pd.Series({'a': 1, 'b': 2, 'c': 3})

# 指定索引
s3 = pd.Series([1, 2, 3], index=['x', 'y', 'z'])

字符串操作

# 去除后缀
series = pd.Series(['SZ#000526.txt', 'SZ#301282.txt'])
series_cleaned = series.str.replace('.txt', '', regex=False)

# 其他方法
series.str.rstrip('.txt')
series.str.slice(0, -4)
series.apply(lambda x: x.replace('.txt', ''))

# 查找包含特定字符串的项
target = "920779"
result = series[series.str.contains(target)]

Series包含DataFrame

# Series可以包含DataFrame对象(但不常见)
df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df2 = pd.DataFrame({'X': [10, 20], 'Y': [30, 40]})
series_of_dfs = pd.Series([df1, df2])

# 更推荐使用字典
data_dict = {
    'dataset1': df1,
    'dataset2': df2
}

数据处理常见问题解决方案

问题1:日期比较类型错误

错误信息Invalid comparison between dtype=datetime64[s] and date

解决方案

# 错误:类型不匹配
# df[df['date'] >= datetime.date(2025,1,1)]

# 正确:统一类型
df[df['date'] >= '2025-01-01']                    # 使用字符串
df[df['date'] >= pd.Timestamp('2025-01-01')]      # 使用Timestamp
df[df['date'] >= np.datetime64(datetime.date(2025,1,1))]  # 使用datetime64

问题2:计算每行多个列的最大值

# 计算open, high, close三个列的最大值
df['max_value'] = df[['open', 'high', 'close']].max(axis=1)

# 带列名标识的版本
def get_max_value_and_column(row):
    values = {'open': row['open'], 'high': row['high'], 'close': row['close']}
    max_col = max(values, key=values.get)
    return pd.Series([values[max_col], max_col])

df[['max_value', 'max_column']] = df.apply(get_max_value_and_column, axis=1)

问题3:去除Series中的文件后缀

series = pd.Series(['SZ#000526.txt', 'SZ#301282.txt'])

# 推荐方法
series_cleaned = series.str.replace('.txt', '', regex=False)

# 其他方法
series.str.rstrip('.txt')
series.str.slice(0, -4)
series.apply(lambda x: x[:-4] if x.endswith('.txt') else x)

问题4:在Series中查找特定字符串

target = "920779"
result = series[series.str.contains(target)]

# 获取索引
indices = series[series.str.contains(target)].index.tolist()

# 获取值
values = series[series.str.contains(target)].tolist()

统计学概念解析

标准差 (Standard Deviation)

基本概念

标准差衡量数据集中各个数据点与平均值的离散程度: - 标准差小:数据点接近平均值,数据集中 - 标准差大:数据点分散,离散程度高

计算公式

总体标准差

σ = √[Σ(xi - μ)² / N]

样本标准差

s = √[Σ(xi - x̄)² / (n - 1)]

NumPy实现

import numpy as np

# 总体标准差 (ddof=0)
std_population = np.std(data, ddof=0)

# 样本标准差 (ddof=1)
std_sample = np.std(data, ddof=1)

# 沿轴计算
std_columns = np.std(matrix, axis=0)  # 每列的标准差
std_rows = np.std(matrix, axis=1)     # 每行的标准差

经验法则(正态分布)

  • 约68.3%的数据落在 μ ± σ 范围内
  • 约95.4%的数据落在 μ ± 2σ 范围内
  • 约99.7%的数据落在 μ ± 3σ 范围内

正态分布 (Normal Distribution)

基本概念

正态分布(高斯分布)是统计学中最重要的概率分布,具有以下特征: - 钟形曲线:对称的钟形形状 - 集中趋势:均值、中位数、众数相等 - 对称性:以均值为中心对称

标准正态分布

  • 均值 μ = 0
  • 标准差 σ = 1
  • 记作:N(0, 1)

NumPy生成正态分布随机数

# 生成标准正态分布随机数
data = np.random.randn(1000)  # 均值为0,标准差为1

# 生成自定义正态分布
data_custom = np.random.normal(loc=100, scale=15, size=1000)  # 均值100,标准差15

# 验证分布特性
mean = np.mean(data)      # 应接近0
std = np.std(data, ddof=1)  # 应接近1

应用场景

  1. 金融:资产收益率建模
  2. 质量控制:产品尺寸测量
  3. 自然科学:测量误差分析
  4. 社会科学:心理测试分数

中心极限定理

无论原始分布是什么,当样本量足够大时,样本均值的分布都趋近于正态分布。

# 中心极限定理演示
sample_means = []
for _ in range(10000):
    sample = np.random.uniform(0, 1, 30)  # 从均匀分布抽样
    sample_means.append(np.mean(sample))

# 样本均值的分布近似正态分布
plt.hist(sample_means, bins=30, density=True)

性能优化建议

NumPy向量化运算

# 推荐:向量化运算
result = array1 + array2

# 避免:Python循环
result = []
for a, b in zip(list1, list2):
    result.append(a + b)

Pandas批量操作

# 推荐:使用向量化方法
df['new_col'] = df['col1'] + df['col2']

# 避免:使用apply循环
df['new_col'] = df.apply(lambda row: row['col1'] + row['col2'], axis=1)

内存优化

# 使用合适的数据类型
df['int_col'] = df['int_col'].astype('int32')
df['float_col'] = df['float_col'].astype('float32')

# 使用分类数据
df['category_col'] = df['category_col'].astype('category')

常用函数速查表

NumPy常用函数

函数 描述 示例
np.array() 创建数组 np.array([1,2,3])
np.arange() 创建等差数组 np.arange(10)
np.linspace() 创建等间隔数组 np.linspace(0,1,5)
np.random.randn() 标准正态分布随机数 np.random.randn(100)
np.mean() 计算平均值 np.mean(data)
np.std() 计算标准差 np.std(data, ddof=1)
np.sum() 计算总和 np.sum(data)

Pandas常用函数

函数 描述 示例
pd.read_csv() 读取CSV文件 pd.read_csv('data.csv')
df.head() 查看前几行 df.head(5)
df.tail() 查看后几行 df.tail(3)
df.info() 数据信息摘要 df.info()
df.describe() 统计描述 df.describe()
df.groupby() 数据分组 df.groupby('category')
df.merge() 数据合并 pd.merge(df1, df2, on='key')
df.pivot_table() 创建透视表 df.pivot_table(values='price', index='date')

注意事项和最佳实践

  1. 数据清洗:始终先检查数据质量和完整性
  2. 类型一致:确保比较操作中的数据类型一致
  3. 内存管理:处理大型数据集时注意内存使用
  4. 代码可读性:优先选择清晰易读的实现方式
  5. 性能考虑:对大型数据集使用向量化操作
  6. 错误处理:对可能失败的操作添加异常处理

总结

NumPy和Pandas是Python数据科学生态系统的核心库: - NumPy:提供高效的数值计算基础 - Pandas:提供灵活的数据结构和数据处理工具

掌握这两个库的使用方法,能够高效地进行数据清洗、转换、分析和可视化,为更复杂的数据科学和机器学习任务奠定基础。


文档更新时间:2024年 整理自Python数据分析相关对话内容