【Python数据科学】Pandas进阶 + NumPy入门,数据分析双剑合璧

从数据处理到数值计算,掌握数据分析核心工具链


先看问题

假设你是一名数据分析师,面对以下场景:

场景1:老板要看每个部门的薪资分布,还要对比不同城市的差异
场景2:需要把销售数据、客户数据、产品数据合并分析
场景3:要计算销售额的环比增长率、移动平均
场景4:数据库里有100万条订单数据,需要快速读取并分析
场景5:要做线性回归预测下季度销售额

这些问题,用 Pandas + NumPy 就能轻松解决!


一、Pandas 进阶:数据处理的瑞士军刀

1.1 groupby 高级用法

import pandas as pd

# 命名聚合(推荐)
df.groupby('department').agg(
    avg_salary=('salary', 'mean'),
    max_salary=('salary', 'max'),
    count=('id', 'count')
)

# 多函数聚合
df.groupby('department')['salary'].agg(['mean', 'max', 'min'])

# 自定义聚合函数
df.groupby('department')['salary'].agg(lambda x: x.max() - x.min())

1.2 pivot_table 透视表

# 类似 Excel 的透视表
pd.pivot_table(
    df,
    values='salary',        # 聚合的值
    index='department',     # 行索引
    columns='gender',       # 列索引
    aggfunc='mean',         # 聚合函数
    fill_value=0,           # 填充空值
    margins=True            # 添加汇总行
)

1.3 merge 数据合并

# 内连接(类似 SQL INNER JOIN)
pd.merge(employees, departments, on='department_id', how='inner')

# 左连接(类似 SQL LEFT JOIN)
pd.merge(employees, departments, on='department_id', how='left')

# 多键连接
pd.merge(df1, df2, on=['city', 'department'], how='inner')

1.4 与数据库交互

from sqlalchemy import create_engine

# 创建连接
engine = create_engine('postgresql://user:password@localhost:5432/mydb')

# 读取数据
df = pd.read_sql('SELECT * FROM employees', engine)

# 写入数据
df.to_sql('new_table', engine, if_exists='replace', index=False)

# 关闭连接
engine.dispose()

二、NumPy:数值计算的基石

2.1 为什么需要 NumPy?

对比项 Python List NumPy Array
性能 快 10-100 倍
内存 分散 连续
运算 需要循环 向量化
类型 任意 固定

2.2 创建数组

import numpy as np

# 从列表创建
arr = np.array([1, 2, 3, 4])

# 全0数组
zeros = np.zeros((3, 4))  # 3行4列

# 全1数组
ones = np.ones(5)

# 序列
arr = np.arange(0, 10, 2)  # [0, 2, 4, 6, 8]

# 随机数
rand = np.random.rand(5)  # 0-1均匀分布
randn = np.random.randn(5)  # 标准正态分布
randint = np.random.randint(1, 100, 5)  # 整数

2.3 数组运算

arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([5, 6, 7, 8])

# 数组间运算(对应位置)
print(arr1 + arr2)  # [6, 8, 10, 12]
print(arr1 * arr2)  # [5, 12, 21, 32]

# 标量运算(每个元素)
print(arr1 * 2)     # [2, 4, 6, 8]
print(arr1 + 10)    # [11, 12, 13, 14]

# 比较运算(返回布尔数组)
print(arr1 > 2)     # [False, False, True, True]

2.4 聚合函数

arr = np.array([15, 23, 42, 87, 56, 12, 34, 67])

print(arr.sum())      # 总和
print(arr.mean())     # 均值
print(arr.std())      # 标准差
print(arr.max())      # 最大值
print(arr.min())      # 最小值
print(arr.cumsum())   # 累计和

2.5 矩阵运算

A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

# 矩阵乘法
print(A @ B)  # 推荐写法
print(np.dot(A, B))

# 转置
print(A.T)

# 逆矩阵
print(np.linalg.inv(A))

# 行列式
print(np.linalg.det(A))

# 特征值
values, vectors = np.linalg.eig(A)

2.6 统计函数

data = np.array([12, 25, 37, 48, 52, 61, 73, 84, 91, 100])

# 均值、中位数、标准差
print(np.mean(data))
print(np.median(data))
print(np.std(data))

# 百分位数
print(np.percentile(data, 25))  # 25%
print(np.percentile(data, 75))  # 75%

# 相关系数
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])
print(np.corrcoef(x, y)[0, 1])  # 接近1表示强相关

三、Pandas vs NumPy 对比

操作 Pandas NumPy
创建 pd.DataFrame() np.array()
索引 标签索引 loc/iloc 位置索引 [0]
运算 自动对齐 对应位置
缺失值 fillna() 有限支持
分组 groupby()
矩阵 @ / dot()
性能 较慢 最快

选择建议

  • 数据分析 → Pandas
  • 数值计算 → NumPy
  • 大数据处理 → NumPy
  • 表格处理 → Pandas

四、踩坑记录

4.1 Pandas 踩坑

坑1:groupby + apply 警告

# ❌ 会警告
df.groupby('department').apply(lambda x: x.sort_values('salary'))

# ✅ 正确写法
df.groupby('department').apply(
    lambda x: x.sort_values('salary'),
    include_groups=False
)

坑2:merge 列名冲突

# 如果两个表有相同列名,会自动加 _x, _y 后缀
pd.merge(df1, df2, on='id')  # name_x, name_y

# 指定后缀
pd.merge(df1, df2, on='id', suffixes=('_left', '_right'))

坑3:to_sql 外键约束

# ❌ 如果表有外键约束,replace 会失败
df.to_sql('departments', engine, if_exists='replace')

# ✅ 先删除外键约束,或换个表名
df.to_sql('departments_new', engine, if_exists='replace')

4.2 NumPy 踩坑

坑1:数组形状不匹配

arr1 = np.array([1, 2, 3, 4])  # shape (4,)
arr2 = np.array([5, 6])        # shape (2,)

# ❌ 会报错
arr1 + arr2  # ValueError: operands could not be broadcast together

坑2:修改视图会影响原数组

arr = np.array([1, 2, 3, 4, 5])
view = arr[0:3]

# ❌ 修改 view 会影响 arr
view[0] = 100
print(arr)  # [100, 2, 3, 4, 5]

# ✅ 使用 copy
copy = arr[0:3].copy()

坑3:整数除法

arr = np.array([1, 2, 3, 4])

# ❌ 整数除法会向下取整
print(arr / 2)  # [0.5, 1. , 1.5, 2. ]  # 实际会返回浮点数

# ✅ 如果要整数结果
print(arr // 2)  # [0, 1, 1, 2]

五、实战案例

5.1 使用 Pandas 分析销售数据

import pandas as pd
from sqlalchemy import create_engine

# 1. 从数据库读取数据
engine = create_engine('postgresql://postgres:password@localhost:5432/mydb')
sales = pd.read_sql('SELECT * FROM sales', engine)

# 2. 数据清洗
sales['date'] = pd.to_datetime(sales['date'])
sales['amount'] = sales['amount'].fillna(0)

# 3. 计算环比增长率
sales['growth_rate'] = sales['amount'].pct_change()

# 4. 分组统计
dept_stats = sales.groupby('department').agg(
    total_sales=('amount', 'sum'),
    avg_sales=('amount', 'mean'),
    count=('id', 'count')
)

# 5. 写回数据库
dept_stats.to_sql('dept_stats', engine, if_exists='replace')

engine.dispose()

5.2 使用 NumPy 做线性回归

import numpy as np

# 模拟数据
np.random.seed(42)
x = np.linspace(0, 10, 50)
y = 3 * x + 5 + np.random.normal(0, 2, 50)

# 最小二乘法拟合
n = len(x)
a = (n * np.sum(x * y) - np.sum(x) * np.sum(y)) / (n * np.sum(x**2) - np.sum(x)**2)
b = (np.sum(y) - a * np.sum(x)) / n

print(f"拟合结果: y = {a:.2f}x + {b:.2f}")
print(f"真实参数: y = 3x + 5")

六、方法速查表

Pandas 常用方法

类别 方法 说明
读取 read_sql() 从数据库读取
写入 to_sql() 写入数据库
分组 groupby().agg() 分组聚合
透视 pivot_table() 透视表
合并 merge() 数据合并
拼接 concat() 数据拼接
环比 pct_change() 环比增长率
排名 rank() 排名

NumPy 常用方法

类别 方法 说明
创建 array(), zeros(), ones() 创建数组
运算 +, -, *, /, @ 数组运算
聚合 sum(), mean(), std() 聚合函数
矩阵 dot(), inv(), det() 矩阵运算
统计 median(), percentile() 统计函数
随机 rand(), randn(), randint() 随机数

七、学习路径

Day 14-16: Pandas 基础(DataFrame、筛选、分组)
    ↓
Day 17-18: Pandas 进阶(透视表、合并、数据库)
    ↓
Day 19-20: NumPy 基础 + 进阶(数组、矩阵、统计)
    ↓
Day 21-22: Matplotlib 可视化
    ↓
Day 23+: 综合项目实战

八、总结

  1. Pandas 是数据处理的瑞士军刀:适合表格数据、数据分析
  2. NumPy 是数值计算的基石:适合矩阵运算、数值计算
  3. 两者配合使用:Pandas 底层依赖 NumPy,可以互相转换
  4. 不用深究数学原理:会用函数就行,数学慢慢补

掌握 Pandas + NumPy,数据分析基本功就扎实了!
下一篇:Matplotlib 数据可视化,让数据说话!

更多推荐