2、数据分析基础回顾:Pandas与NumPy核心操作、数据清洗流程、探索性数据分析(EDA)基础

好,咱们正式开始第二讲。说实话,很多同学一上来就急着学 Prompt 怎么写,结果数据长什么样都没搞清楚。我见过太多这样的案例了——Prompt 写得花里胡哨,结果喂进去的数据全是脏的,模型输出自然一塌糊涂。所以今天,咱们先把地基打牢。

这一章我会带你快速过一遍 Pandas 和 NumPy 的核心操作,然后聊聊数据清洗的常规流程,最后说说探索性数据分析(EDA)到底该怎么做。嗯,都是我在项目里反复用到的套路。

2.1 NumPy 核心操作:数组与向量化计算

NumPy 是 Python 数据科的基石。说白了,它就是给 Python 装上了「矩阵运算」的引擎。我个人习惯把 NumPy 当作所有数值计算的底层加速器。

2.1.1 创建数组

import numpy as np

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

# 全零数组
zeros = np.zeros((3, 4))

# 等差数列
seq = np.arange(0, 10, 2)  # [0, 2, 4, 6, 8]

# 随机数组
rand = np.random.randn(3, 3)  # 标准正态分布
我的小习惯:创建测试数据时,我特别喜欢用 np.random.seed(42) 固定随机种子。为什么?因为这样每次跑出来的结果都一样,调试起来特别省心。我曾经因为忘了设种子,排查了半天才发现是数据每次都不一样。

2.1.2 向量化运算

这是 NumPy 最牛的地方。你想想看,如果用 Python 原生循环去算 100 万个数的平方,那得等到猴年马月?但 NumPy 一行搞定:

data = np.array([1, 2, 3, 4, 5])
squared = data ** 2  # 向量化,速度比循环快几十倍

# 条件筛选
mask = data > 2
filtered = data[mask]  # [3, 4, 5]
注意:向量化运算虽然快,但会消耗更多内存。我在处理 10GB 级别的数据时,就吃过这个亏——内存直接爆了。这时候就要考虑分块处理或者用生成器了。

2.2 Pandas 核心操作:DataFrame 与 Series

Pandas 是数据分析的瑞士军刀。我个人觉得,80% 的数据分析工作都可以用 Pandas 完成。它的核心就两个东西:DataFrame(表格)和 Series(一列数据)。

2.2.1 读取与查看数据

import pandas as pd

# 读取 CSV
df = pd.read_csv('sales_data.csv')

# 快速预览
df.head(10)      # 前10行
df.info()        # 列信息、非空值数量、数据类型
df.describe()    # 数值列的统计摘要

你想想看,拿到一个新数据集,第一件事是什么?我建议先跑 df.info()。它能告诉你三件事:有多少行、每列是什么类型、有没有缺失值。嗯,这三件事决定了你后续所有操作的策略。

2.2.2 数据选择与过滤

# 选择列
df['customer_name']          # 单列,返回 Series
df[['name', 'age', 'city']]  # 多列,返回 DataFrame

# 行过滤
df[df['age'] > 30]           # 年龄大于30的行
df[(df['age'] > 30) & (df['city'] == '北京')]  # 多条件

# 位置索引
df.iloc[0:5, 0:3]            # 前5行,前3列
核心原则:[] 选列,用 loc/iloc 选行。别搞混了,我刚开始学的时候经常写反,结果报错报得一脸懵。

2.2.3 分组与聚合

分组聚合是数据分析的「灵魂操作」。说白了就是「按某个维度拆开,分别算点东西,再拼回来」。

# 按城市分组,计算平均销售额
df.groupby('city')['sales'].mean()

# 多维度分组,多个聚合函数
df.groupby(['city', 'product']).agg({
    'sales': ['sum', 'mean'],
    'quantity': 'sum'
})

我记得有一次做电商数据分析,需要按「城市+品类」统计销售额占比。用 groupbytransform 一行就搞定了,旁边同事还在写 Excel 透视表...嗯,从那以后我就再也没打开过 Excel。

2.3 数据清洗流程:从脏数据到干净数据

数据清洗是数据分析里最耗时、最枯燥、但也最重要的环节。我做过一个统计:一个数据分析项目,60% 的时间花在清洗上,30% 花在理解业务上,只有 10% 是真正的建模和分析。

2.3.1 处理缺失值

# 检查缺失值
df.isnull().sum()

# 删除缺失值(谨慎使用)
df.dropna()  # 删除任何包含缺失值的行

# 填充缺失值
df['age'].fillna(df['age'].median(), inplace=True)  # 用中位数填充
df['city'].fillna('未知', inplace=True)              # 用固定值填充
我曾经踩过的坑:有一次我直接 dropna() 删掉了 30% 的数据,结果模型训练出来偏差特别大。后来才发现,缺失值其实是有规律的——低收入人群更倾向于不填收入字段。所以,永远不要无脑删除缺失值,先搞清楚它为什么缺失。

2.3.2 处理重复值

# 检查重复行
df.duplicated().sum()

# 删除重复行(保留第一个)
df.drop_duplicates(inplace=True)

# 按指定列判断重复
df.drop_duplicates(subset=['user_id', 'date'], keep='last')

2.3.3 数据类型转换

# 转换数据类型
df['date'] = pd.to_datetime(df['date'])  # 字符串转日期
df['price'] = df['price'].astype(float)  # 强制转浮点数

# 处理异常值(比如价格不可能为负数)
df = df[df['price'] > 0]
一个小技巧:pd.to_datetime() 时,如果数据格式不统一,可以加 errors='coerce' 参数。这样无法解析的日期会变成 NaT,而不是直接报错中断程序。我几乎每次都用这个参数。

2.4 探索性数据分析(EDA)基础

EDA 是什么?说白了就是「先别急着建模,先看看数据长什么样」。我见过太多人拿到数据就开跑模型,结果跑出来一堆垃圾。嗯,EDA 就是帮你避免这种尴尬的。

2.4.1 单变量分析

先看每一列自己的分布情况:

# 数值型:看分布
df['age'].hist(bins=30)           # 直方图
df['age'].describe()              # 统计摘要

# 类别型:看频次
df['city'].value_counts()         # 各城市数量
df['city'].value_counts(normalize=True)  # 占比

为什么会先看单变量?因为你能发现很多「一眼假」的问题。比如年龄分布里突然出现一个 200 岁的,或者城市字段里有个「北京市」和「北京」两个写法——这些都是数据质量问题。

2.4.2 双变量分析

看两个变量之间的关系:

# 数值 vs 数值:散点图
df.plot.scatter(x='age', y='income')

# 类别 vs 数值:箱线图
df.boxplot(column='income', by='city')

# 相关性矩阵
df.corr()  # 数值列的相关系数
我的经验:相关性矩阵是个好东西,但别只看数字。我记得有一次两个变量的相关系数高达 0.95,我兴奋得不行,结果画出来一看——是时间序列的伪相关。所以,一定要可视化验证,别只看数字。

2.4.3 多变量分析

# 用 seaborn 画 pairplot(需要安装 seaborn)
import seaborn as sns
sns.pairplot(df[['age', 'income', 'spend', 'score']])

Pairplot 能让你一眼看出所有数值变量两两之间的关系。嗯,我每次做 EDA 都会跑一下这个图,虽然数据多的时候会有点慢,但值得等。

2.5 总结:数据分析的「三板斧」

好了,咱们来捋一捋。这一章的核心就三件事:

  1. NumPy 做底层计算——向量化、矩阵运算、随机数
  2. Pandas 做数据处理——读取、过滤、分组、聚合
  3. 数据清洗 + EDA——处理缺失值、重复值、异常值,然后可视化探索

我个人觉得,这三板斧练好了,80% 的数据分析场景你都能应付。下一章咱们就要开始讲 Prompt 工程了——但记住,没有干净的数据,再牛的 Prompt 也是白搭

课后练习建议:找一份真实的 CSV 数据(比如 Kaggle 上的 Titanic 数据集),按照本章的流程完整走一遍:读取 → 查看 → 清洗 → EDA。别偷懒,动手做一遍比看十遍都管用。

好,这一章就到这儿。有什么问题咱们下节课聊。