为什么数据科学从 NumPy 开始

Python 之所以成为数据科学的主流语言,不是因为语法优雅,而是因为它有一套层次分明的计算生态:NumPy 负责同构数值数组,Pandas 负责带标签的表格数据,Matplotlib 负责出图。三者叠加,覆盖了从读取到分析再到呈现的完整链路。

很多人跳过 NumPy 直接学 Pandas,结果遇到性能问题或维度问题时无从下手。实际上 Pandas 的底层就是 NumPy,理解 ndarray 的形状、广播与向量化,是后面一切的基础。

数据分析的效率,取决于你能不能把循环换成向量化运算——这是 NumPy 教给你的第一课,也是最重要的一课。

如果你的环境还没装好,一句 pip install numpy pandas matplotlib 就够用了。接下来我们按“数组 → 表格 → 清洗 → 聚合 → 出图”的顺序推进。

ndarray:向量化运算的威力

ndarray 的核心特征是同构(所有元素类型一致)和定长(形状固定),这让它可以连续存储、批量运算。把 Python 的 for 循环换成数组运算,速度常常有几十倍的差距。

NumPy 必会四件事
  • 形状shape 表示各维长度,reshape 与 [:, None] 是构造多维数据最常用的手法。
  • 向量化用 arr * 2 替代逐元素循环,由底层 C 代码执行。
  • 广播形状不同的数组按规则自动对齐,避免手工复制数据。
  • 布尔索引arr[arr > 0] 直接完成筛选,是 Pandas 条件筛选的底层机制。
Python 数据分析示意:左侧数据表格逐列拆解为飘浮数据条,右侧汇聚成上升的折线图
从表格到图表:数据科学的工作流,本质是把结构化的行与列变换成可解释的结论。

一个常见陷阱是原地操作:arr += 1 会修改原数组,而 arr = arr + 1 会新建对象。在函数里传参时要特别小心,必要时用 arr.copy() 明确复制。

Pandas 的两大数据结构

Pandas 提供了两个结构:Series(带索引的一维数组)和 DataFrame(带行列标签的二维表)。可以把 DataFrame 理解为“多个共享索引的 Series”,这也是它按列运算高效、按行遍历缓慢的原因。

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "order_id": [1001, 1002, 1003, 1004, 1005],
    "city": ["佛山", "广州", "佛山", "深圳", "广州"],
    "amount": [128.0, 89.5, np.nan, 320.0, 45.0],
    "qty": [2, 1, 3, 5, 1],
})
print(df.dtypes)                                    # 逐列类型
print(df.head(3))                                   # 前 3 行
print("平均客单价:", round(df["amount"].mean(), 2))   # nan 被自动跳过 → 145.62

选择数据时优先用 loc(按标签)和 iloc(按位置),避免链式索引 df[df.a > 1]["b"],因为它可能返回视图而非副本,赋值时会静默失效——这是最常见也最难排查的 Pandas 陷阱。

数据清洗:缺失值、重复与类型

真实数据一定脏。清洗通常占整个分析流程六成以上的时间,标准动作有四个。

  • 缺失值:先判断是“随机缺失”还是“系统性缺失”。数值用中位数填充,类别用众数或单列“未知”,缺失比例过高的列直接删除。
  • 重复值:用 subset 指定判定列做去重,保留最新一条。
  • 类型与格式:金额、日期、ID 常被读成字符串,需要显式转换并处理异常值。
  • 异常值:用分位数或业务规则识别,不要无脑删除——异常往往才是分析的重点。
# 清洗:类型转换、去重、派生列
df["amount"] = pd.to_numeric(df["amount"], errors="coerce")
df = df.dropna(subset=["amount"]).drop_duplicates(subset=["order_id"])
df["city"] = df["city"].astype("category")
df["unit_price"] = df["amount"] / df["qty"]
print(df.isna().sum())          # 逐列统计缺失数量
print(df.describe())            # 数值列的分布概况

建议把每一步清洗都写成独立函数并加注释:数据管道要被别人读懂,也要能在三个月后重新跑一遍。把清洗逻辑留在 Notebook 的临时单元格里,是团队协作中最容易埋雷的做法。

分组聚合:用 groupby 回答问题

groupby 是回答业务问题的主力:把数据按某个维度切分,再对每个分组做聚合。它的心智模型是“拆分 → 应用 → 合并”。

常见聚合包括 sum、mean、count、nunique(去重计数)以及自定义函数。多列聚合用 agg 传字典或命名元组;分组结果要保留原表宽度时用 transform 而不是 agg——这是最容易踩的坑之一,用错了会得到形状不匹配的报错。

透视表 pivot_table 可以理解为 groupby 的表格化表达,把行、列、值、聚合方式一次配齐,输出直接可读。做月度 × 品类的交叉分析时,它比手写多层 groupby 清晰得多。

可视化:把结论画出来

图表的价值是让结论在一秒内被理解。三个基本原则:一图一结论,不要把五条曲线塞进同一张图;坐标轴从零开始(除非有充分理由截断);标注单位与样本量。

常用图形与用途:折线图看趋势,柱状图比大小,箱线图看分布与离群点,散点图看相关性与聚类倾向,热力图看二维交叉强度。Matplotlib 负责精细控制,Seaborn 负责统计图形的快速出图。

作图前先明确你想让读者记住什么,再选图形;而不是先选一个好看的图,再想办法塞数据。另外记得在服务器或无界面环境里把后端设为 Agg,否则会因为缺少图形界面直接报错。