如果你正在自学数据科学,大概也经历过这样的阶段:pandas能读 Excel 了,matplotlib能画图了,甚至简单调过几次sklearn里的模型。可拿到一份真实业务数据时,还是不知道第一步该干什么——是先清洗还是先查库?特征怎么构造?模型效果不稳怎么办?数据大到单机跑不动怎么办?
我见过不少初学者把大量时间花在“学会某个函数”上,却始终没有建立一条从数据到结论的完整链路。UC Berkeley 的本科核心课 Data 100,恰恰就是为解决这个问题设计的。它不是一门只讲工具的课,而是一门把 pandas、SQL、机器学习、Spark 串成一条完整数据科学流程的高密度课程。中文学习者现在也能找到带中英双语字幕的完整版本,能看懂专业术语,也能对照英文表达,学习门槛比过去低了很多。
这篇文章会拆解 Data 100 的课程结构、每个技术栈应该掌握到什么程度、怎样在本地复现课程环境,以及最容易踩的坑。如果你正在规划数据科学学习路径,或者已经学了一些碎片化知识但串不起来,这篇内容值得你收藏后慢慢读。
1. 为什么 UC Berkeley 的 Data 100 值得系统看一遍
先给一个明确判断:Data 100 真正稀缺的地方,不是某个工具讲得有多深,而是它把“数据科学全流程”这条主线贯穿始终。
很多在线教程的问题是太零散。讲 pandas 的教程只讲 DataFrame,讲 SQL 的教程只讲增删改查,讲机器学习的教程一上来就调库。结果就是你学完之后,并不知道这些工具在真实项目里是如何协同工作的。Data 100 不一样,它是按“拿到数据 -> 清洗规整 -> 查询取数 -> 特征工程 -> 建模评估 -> 分布式扩展”的顺序来组织的,每讲都在告诉你当前这一步处在全流程的哪个位置。
从公开材料来看,这门课是 UC Berkeley 本科高年级的核心课,定位已经默认学生具备基础 Python 能力。它不会花时间教你怎么写 for 循环,而是把精力放在数据科学真正棘手的地方:数据质量极差怎么办、特征怎么构造才合理、模型评估怎么做才可靠、数据量大到单机内存装不下怎么办。
对以下人群尤其有价值:
- 正在自学数据分析或数据科学,但知识碎片化的同学;
- 做过一些 Python 数据处理,想系统补齐机器学习与 SQL 能力的开发者;
- 想转行数据方向、需要一个高密度实战课程的职场人;
- 有一定工程经验,但想了解数据科学流程和工程流程如何结合的工程师。
一句话总结:如果你只想学一个“API 大全”,Data 100 不是最优选择;但如果你想建立数据科学的整体思维,它是目前公开课程里很值得参考的体系之一。
2. 课程概览:一门课如何讲完数据科学全流程
2.1 课程定位与主线
Data 100 全称是 “Principles and Techniques of Data Science”,核心目标不是培养算法研究员,而是培养能处理真实数据、能沟通数据结论的数据科学工程人才。
这门课把数据科学拆成几个关键阶段:
| 环节 | 核心技术 | 你要掌握的能力 |
|---|---|---|
| 数据获取与规整 | pandas | 读取不同格式文件、处理缺失值、类型转换、去重、合并 |
| 数据查询 | SQL | 从数据库取数、聚合统计、窗口函数、查询优化思路 |
| 探索性分析与可视化 | pandas / matplotlib | 发现分布异常、验证假设、形成特征想法 |
| 建模与评估 | scikit-learn | 构建特征、划分数据集、训练模型、交叉验证、分析偏差方差 |
| 大规模数据处理 | Spark | 理解分布式计算原理、处理单机放不下的数据 |
注意这个顺序:它不是把工具孤立地讲完,而是按一条真实项目流程来推进。你在前面用 pandas 清洗好的数据,后面会成为 SQL 查询的输入;你通过 SQL 聚合出来的特征,会成为机器学习模型的输入;当数据规模涨到单机处理不了时,Spark 才登场。
2.2 为什么这门课适合用来建立全流程认知
大多数初学者最大的问题是“不知道当前这一步在干什么”。例如用pd.read_excel()读进来一个 DataFrame,接下来是直接跑模型吗?不是。中间还有类型检查、缺失值判断、重复值处理、异常值分析、特征构造等大量工作。
Data 100 的作业设计也突出了这一点:作业不是让你调用某个 API 结束,而是给一份真实数据,让你从头完成清洗、分析、建模、评估和结论描述。这种“从数据到结论”的练习,比单独刷十遍语法题都有效。
2.3 适合人群与前置要求
建议你有以下基础再学,收获会大很多:
- 熟悉 Python 基本语法,写过简单的函数与循环;
- 了解 NumPy 数组的基本概念;
- 知道 DataFrame 大致是什么,哪怕没用过几次;
- 对机器学习没有系统学过也没关系,课程会带你建立基本框架。
如果你的 Python 还不太熟,建议先补一些基础语法,再来接触 Data 100,否则容易在环境配置和语法细节上消耗过多精力。
3. 第一站 pandas:数据清洗不是“凑合用”
3.1 为什么从 pandas 开始
真实数据几乎不可能是干净的。CSV 里混着中文逗号、Excel 表格里有合并单元格、用户 ID 有的是字符串有的是数字、日期格式五花八门。这些问题的处理方式,就是 pandas 的核心价值所在。
很多初学者以为 pandas 只是用来读取文件、画个统计图的工具,这是很大的误解。pandas 的真正难点在于“数据规整”:把脏数据变成标准的结构化数据,让后续分析和建模可以顺利进行。Data 100 把 pandas 放在课程早期,原因就是后面所有内容都依赖前面这份被清洗干净的数据。
3.2 实战:读取 Excel、类型转换与缺失值处理
这里我们写一个最小示例,演示数据清洗中最高频的三个操作:读取 Excel、类型转换、缺失值处理。这个示例不用依赖任何课程作业数据,你可以直接用自己手头的一份表格测试。
import pandas as pd from pathlib import Path # 1. 读取 Excel 文件 # 注意:读 Excel 需要额外安装 openpyxl 或 xlrd 引擎 file_path = Path("data/user_data.xlsx") df = pd.read_excel(file_path, sheet_name=0) # 2. 查看每列数据类型,这一步非常关键 print("清洗前的列类型:") print(df.dtypes) print("数据量:", len(df)) # 3. 类型转换:年龄列转成数值,非法值变成 NaN df["age"] = pd.to_numeric(df["age"], errors="coerce") # 4. 日期解析:把字符串日期转成标准 datetime df["created_at"] = pd.to_datetime(df["created_at"], errors="coerce") # 5. 删除完全重复的用户记录 df = df.drop_duplicates(subset=["user_id"]) # 6. 缺失值处理:年龄缺失用中位数填充 df["age"].fillna(df["age"].median(), inplace=True) # 7. 按城市聚合,得到一份可以直接用于分析的结果 summary = df.groupby("city", as_index=False).agg( user_count=("user_id", "nunique"), avg_age=("age", "mean") ) print("清洗后的聚合结果:") print(summary.head())这段代码虽然短,但覆盖了数据清洗 80% 的常见操作:读取、看类型、转类型、转日期、去重、填缺失值、分组聚合。执行前建议先打印df.dtypes和df.describe(),肉眼检查一下有没有明显异常。
3.3 初学者最容易踩的坑
第一个坑是pd.read_excel()报错,提示缺少openpyxl。这不是 pandas 本身的问题,而是 Excel 文件需要额外的引擎支持,装上openpyxl即可。
第二个坑是类型转换失败。例如一列数据里混入了"unknown"这样的字符串,pd.to_numeric()会直接报错。这时要用errors="coerce"把非法值变成NaN,再统一处理缺失值。
第三个坑是日期格式混乱。有人习惯用"2024/01/15",有人用"2024-01-15",还有人用"20240115"。pd.to_datetime()能处理大多数常见格式,但仍然建议先抽样打印几行确认。
4. 第二站 SQL:取数能力经常被低估
4.1 SQL 在数据科学中的位置
许多人的学习路径里,SQL 是最后才补的一环。但真实的数据科学项目中,SQL 往往是最先发生的动作:数据存在数据库里,你要先写查询取出需要的字段,再在 Python 中进行分析。Data 100 安排 SQL 内容的逻辑也很清楚:不是让你成为数据库管理员,而是让你具备“自主取数”能力。
一个能写复杂 SQL 的人,和一个只会用 pandas 读 CSV 的人,在生产环境中的效率差异非常大。前者可以自助获取某段时间、某类用户的数据,后者每次都要等别人从库里导出文件。
4.2 窗口函数的典型用途
数据分析里最常见的查询优化问题,就是“取每个用户最近一笔订单”或“计算每个用户的累计金额”。这类需求靠普通GROUP BY很难实现,但用窗口函数会非常直观。
SELECT order_date, user_id, order_amount, -- 按用户分组,按订单日期倒序编号 ROW_NUMBER() OVER ( PARTITION BY user_id ORDER BY order_date DESC, order_id DESC ) AS order_seq, -- 按用户分组,计算截止当前行的累计金额 SUM(order_amount) OVER ( PARTITION BY user_id ORDER BY order_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS running_amount FROM orders WHERE order_date >= '2025-01-01' AND order_amount > 0;这里ROW_NUMBER()用来定位“每个用户的第几笔订单”,SUM() OVER (...)用来计算累计值。实际业务中,这两类逻辑非常常见:用户生命周期分析、留存分析、漏斗分析都会用到。
拿到上述结果后,再配合WHERE order_seq = 1,就能筛选出每个用户最近一笔订单,这是普通分组写法很难做到的场景。
4.3 慢 SQL 优化从哪里下手
不少同学的 SQL 能跑出来,但数据量一大就慢得离谱。优化思路通常遵循这几个方向:
- 避免
SELECT *,只取需要的字段,减少 IO; - 对过滤字段建立索引,尤其是日期、用户 ID 这类高频查询字段;
- 查看执行计划,确认是否发生全表扫描,关键字段是否走了索引;
- 尽量在 SQL 层面先缩小数据范围,再和别的表关联;
- 大数据量排序和窗口函数要注意分区设置,避免单节点压力过大。
记住一个原则:能早过滤就早过滤,能用数据库完成的计算就不要把几百万行数据拉到 Python 里再处理。这也是 Data 100 强调全流程的原因之一——每个工具都应该放在它最合适的环节。
5. 第三站 机器学习:从干净数据到可解释模型
5.1 课程串联 ML 的视角
Data 100 讲机器学习,不是从数学公式开始的。它的切入点是:你已经有一份清洗好的表格,里面有特征列,也有目标列,现在要建立一个模型来预测目标变量。这个视角非常工程化,也恰恰是大多数入门者需要的。
课程会反复强调几个关键概念:训练集与测试集必须严格分开;交叉验证能更可靠地评估模型;特征工程对模型效果的影响往往比调参更大;模型的解释性有时比精度更重要。
5.2 最小可运行示例:Pipeline + 交叉验证
下面用一个 sklearn 的 Pipeline 演示完整建模流程。Pipeline 的好处是能把“特征处理 + 模型训练”打包成一个整体,避免在训练集和测试集上分别做预处理时发生数据泄漏。
import pandas as pd from sklearn.compose import ColumnTransformer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.ensemble import RandomForestClassifier from sklearn.pipeline import Pipeline from sklearn.model_selection import train_test_split, cross_val_score # 假设 df 是已经清洗好的数据 df = pd.DataFrame({ "age": [25, 34, 45, 29, 52, 31], "amount": [100, 320, 210, 540, 80, 300], "city": ["北京", "上海", "广州", "北京", "上海", "广州"], "channel": ["app", "web", "app", "web", "app", "web"], "churn": [0, 1, 0, 1, 0, 1] }) X = df.drop(columns=["churn"]) y = df["churn"] num_features = ["age", "amount"] cat_features = ["city", "channel"] preprocessor = ColumnTransformer([ ("num", StandardScaler(), num_features), ("cat", OneHotEncoder(handle_unknown="ignore"), cat_features) ]) model = Pipeline([ ("prep", preprocessor), ("clf", RandomForestClassifier(n_estimators=100, random_state=42)) ]) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) model.fit(X_train, y_train) # 交叉验证:用 5 折验证模型稳定性 scores = cross_val_score(model, X_train, y_train, cv=5) print("交叉验证准确率:", scores.mean()) print("测试集准确率:", model.score(X_test, y_test))代码里的ColumnTransformer解决了分类变量和数值变量需要不同预处理的问题:数值列做标准化,分类列做独热编码,然后统一送入随机森林。这个模式在真实项目中使用频率非常高,Data 100 也会在作业中反复用到类似结构。
5.3 评估与过拟合
机器学习部分最容易忽略的是评估。很多新手只看准确率,一旦准确率高就觉得很满意。实际上更值得关注的是:
- 训练集和测试集分数差距很大,说明过拟合了;
- 使用交叉验证比单次切分更可靠;
- 分类问题除了准确率,还要看精确率、召回率、F1;
- 样本不平衡时,准确率可能非常有欺骗性。
Data 100 的价值在于把这些“工程套路”放在课程主线里,而不是等你踩完坑再回头补。认真做一遍课后作业,对这种流程的感受会非常明显。
6. 第四站 Spark:单机撑不住时的分布式方案
6.1 为什么需要 Spark
pandas 处理 1GB 数据可能还行,但面对 100GB 甚至更大的日志数据时,单机内存往往直接溢出。Spark 的核心思想是把数据分到多个节点、多个 Executor 上并行处理,每一台机器只处理一部分数据,最后汇总结果。
Data 100 讲 Spark 的定位不是让你成为一个 Spark 调优专家,而是让你理解:当数据规模超过单机上限时,之前的 pandas 代码思路如何迁移到分布式环境。两者在 DataFrame 的 API 上非常接近,这也降低了学习成本。
6.2 环境搭建与第一个 Spark 程序
在本地做小规模实验,最轻量的方式是直接用 pip 安装 PySpark,不需要单独搭建 Hadoop 集群。
pip install pyspark安装完成后,运行一个最小的 Spark 程序:
from pyspark.sql import SparkSession from pyspark.sql import functions as F # local[*] 表示使用本机所有可用 CPU 核心 spark = SparkSession.builder \ .appName("data100_demo") \ .master("local[*]") \ .getOrCreate() # 读取带表头的 CSV 文件,自动推断数据类型 df = spark.read.csv("data/events.csv", header=True, inferSchema=True) # 统计每个用户产生的事件数量,并降序排列 result = df.filter(F.col("event_type") == "click") \ .groupBy("user_id") \ .count() \ .orderBy(F.col("count").desc()) result.show(10) spark.stop()这段代码的结构和 pandas 非常像:filter相当于df[df["event_type"] == "click"],groupBy().count()相当于df.groupby().size()。迁移成本并没有想象中高。
6.3 内存与资源调度:最常见的坑
Spark 部分初学者最容易遇到的问题,不是 API 用错,而是资源不生效。比如明明集群有几个节点,作业却只跑在一个 Executor 上;或者设置了很大的 Executor 内存,实际运行还是很慢。
从常见情况来看,多数问题出在:
master设置不对,本地程序默认没有并行到多节点;- Executor 的 CPU 和内存配置与 Yarn 的资源队列不匹配;
- 数据没有做合理的分区,导致部分 Executor 闲置;
- 每次
collect()一大份数据到 Driver 端,导致 Driver 内存溢出。
当你遇到“Executor 在 Yarn 上运行时,每个 Container 只分配了一个 vCore”这类现象时,第一反应应该是检查资源调度配置,而不是怀疑 Spark 本身。这个问题在面试和实际运维中都频繁出现,值得在学 Spark 时多看一眼。
7. 本地环境搭建与学习节奏建议
7.1 推荐环境组合
在本地复现 Data 100 的实验,最推荐的环境组合是 Python + Jupyter Notebook + pandas + scikit-learn + PySpark。不建议一开始就去搭建 Hadoop 集群,先用local[*]模式把流程跑通,理解原理后再考虑分布式部署。
这里给出一套完整的环境安装命令,适合在 conda 环境中执行:
conda create -n data100 python=3.11 -y conda activate data100 pip install pandas openpyxl scikit-learn pyspark jupyter matplotlib其中openpyxl是pd.read_excel()的底层引擎,缺了它无法读取 Excel 文件。matplotlib用于可视化,jupyter用于交互式实验。
7.2 PyCharm 里如何安装 pandas 包
很多读者习惯用 PyCharm 做开发。在 PyCharm 中安装 pandas 有两种常见方式:
第一种,打开左下角的Python Packages窗口,搜索pandas,点击Install即可。第二种,使用pip命令,在 PyCharm 的终端中执行:
pip install pandas如果你使用的是 conda 环境,先确认当前解释器是 conda 环境再安装,避免装到了另一个环境里。判断方法很简单:查看 PyCharm 右下角或设置里的 Python Interpreter 路径,确认为当前项目环境即可。
7.3 学习节奏建议
Data 100 内容密度较高,不建议一天刷完。更合理的节奏是一周消化 3 到 4 讲,并同步完成对应作业:
- 第一周:pandas 数据清洗,配合 Excel 和 CSV 数据做强化练习;
- 第二周:SQL 查询与窗口函数,建议自己在本地启动一个 SQLite 或 MySQL 练习;
- 第三周:机器学习基础与 sklearn Pipeline,跑通分类和回归各一个案例;
- 第四周:Spark 原理与 PySpark DataFrame,用一份较大的数据验证分布式处理思路。
每学一个阶段,都在自己的项目里尝试一下。例如用 pandas 清洗你手机里的通话记录,用 SQL 查询一个开源数据集的统计结果,用 sklearn 预测一个分类问题。这样学完课程,等于同时积累了自己的三个小项目。
8. 数据科学全流程常见问题排查表
在实际学习和复现过程中,下面这些问题是出现频率很高的,建议直接保存备用。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| pandas 读 Excel 报错 Missing optional dependency 'openpyxl' | 缺少 Excel 读取引擎 | 查看错误信息尾部提示 | pip install openpyxl |
pd.to_numeric()报错无法解析 | 列中包含非数字字符串 | 打印该列唯一值 | 加errors="coerce",把非法值转 NaN |
| 日期列转完后变成 NaT 或格式不对 | 日期字符串格式不统一 | 抽样打印原始值 | 先标准化再pd.to_datetime(),或用format参数指定格式 |
| SQL 窗口函数结果与预期不符 | 对PARTITION BY和ORDER BY理解不准确 | 先跑一个只有几行数据的子集验证 | 手动模拟窗口计算过程,再对比结果 |
| 机器学习训练集分数很高但测试集很低 | 过拟合 | 对比 train/test 分数,查看特征数量 | 使用交叉验证、减少特征、增加正则化或数据量 |
| Spark 作业没有并行加速效果 | master 设置或资源分配不当 | 查看 Spark UI 中的 Executor 数量 | 检查local[*]或 Yarn 资源队列配置 |
| PySpark 读取中文 CSV 乱码 | 文件编码不是 UTF-8 | 查看文件原始编码 | 读取时指定encoding="utf-8"或"gbk" |
| 导入 skearn 报错依赖冲突 | 多个 Python 环境混乱 | 检查当前解释器路径 | 统一使用 conda 环境,重新安装依赖 |
先定位问题所处的环节,再针对性地查日志和配置,通常比盲目搜索报错信息更有效。
9. 学习 Data 100 应该避开的坑与工程建议
9.1 不要只看视频,作业才是核心
视频是课程体系的引导,真正让你产生能力提升的是课后作业。如果时间有限,宁可加快视频速度,也要留出足够时间做作业。Data 100 的作业设计有很强的工程性,很多细节如数据清洗顺序、特征选择、评估方式,都是在作业里才能真正体会到的。
9.2 建立自己的 Notebook 模板
准备一个“数据清洗模板”和“建模模板”,把自己常用的代码块整理好,例如 Excel 读取、类型转换、缺失值处理、train_test_split、Pipeline 构建。以后拿到新数据,直接套用模板,再针对具体情况进行调整。这个习惯能显著提升你的工作效率。
9.3 把课程项目改造成自己的作品
只完成课程作业,作品集里依然写的是“课程项目”。更好的做法是:把课程学到的方法迁移到一份你感兴趣的数据上,比如公开的电商数据集、天气数据、球队比赛数据。做一个小的分析报告,写清楚数据来源、清洗过程、分析结论和模型评估,这比写“我完成了 XX 课的作业”有说服力得多。
9.4 警惕“工具熟练度假象”
能调用 API 不等于理解原理。比如会用pd.to_numeric(),不代表你知道为什么要先检查 dtype;会用train_test_split(),不代表你明白为什么不能先做全量标准化再划分。Data 100 强调全流程,本质上是希望你理解每一步操作背后的原因。做任何一步操作前,先问自己:如果没有这一步,结果会有什么不同?
真正把 Data 100 学透的人,不是记住了多少函数,而是建立了从业务问题到数据答案的完整路径。工具会更新、版本会迭代,这种全流程思维才是你后续学习更高级数据科学内容的地基。建议收藏本文,按照第七节的环境搭建步骤先把本地实验环境跑通,然后开始系统观看课程。整个过程不需要一次到位,但要保证每一步都亲手敲过代码、看过输出、调试过错误。这样学下来,你会明显感觉到自己的数据科学能力上了一个台阶。