简介:Python数据科学手册是一份经典且实用的学习资料,面向希望系统学习数据科学的Python初学者、数据分析师及科研人员,也适合作为相关课程的辅助参考。手册既有理论知识讲解,也配有可直接运行的源代码,读者可以通过动手练习掌握数据清洗、统计分析、可视化展示与建模评估的完整流程,从而提升实际分析能力。压缩包为RAR格式,整体约47.11MB,内部包含PDF文档与源代码文件,PDF便于阅读批注,源代码可按章节运行调试,适合配合教材逐章实践。该资源在CSDN平台已有742人学习下载,来源于用户weixin_42666807,具有一定口碑。获取后可以省去零散找资料的麻烦,既能通读全册建立知识框架,又能对照代码完成图形绘制、特征处理等典型任务,是一份适合入门与进阶的性价比很高的数据科学自学材料。
1. Python数据科学手册:它不是一本看完就走的书,而是工作台
很多人入门数据科学时,电脑里同时开着十几个网页,一个讲 NumPy 切片,一个讲 pandas 分组,一个讲 Matplotlib 配色,还有一个在讲机器学习算法。信息本身没问题,但脑子的知识是散线,真正面对一份带脏数据的 CSV 时,这些线根本连不起来。Python数据科学手册这类材料之所以被反复推荐,就是因为它按“从数据准备到建模验证”的流程来组织内容,把 Python 生态里常用的库串成了一条可以完整走通的路径。它适合想用 Python 进入数据科学的初学者,也适合长期写业务代码但对数据处理缺少系统手感的人。这本手册的正确用法是把它当成工作台,不是收藏夹——每段代码都跑一遍,然后换成自己的数据。
2. 先把地基打牢:Python 环境、依赖管理与数据科学库的选型
2.1 Python 解释器与虚拟环境:为什么环境问题总是第一个绊倒新手
数据科学手册里的示例几乎都依赖 NumPy、pandas 这些第三方库,而这些库对 Python 版本有明确要求。我通常建议直接装 Python 3.10 或 3.12,不追最新,更不要停留在 2.7。原因很实际:太老的版本装新库会报编译错误;太新的版本反而可能有一些底层扩展还没发布对应的二进制包。先确认自己机器的 Python 情况,再做下一步:
python --version pip --version如果没有输出,说明解释器没装好,或是没有把 Python 加入 PATH。Windows 用户在安装时记得勾选“Add Python to PATH”,macOS/Linux 用户一般用 python3 命令来区分系统自带的旧版。
环境隔离这块,我建议每个数据科学项目都建一个虚拟环境,而不是直接往系统环境里装全家桶。虚拟环境可以把当前项目的依赖独立出来,避免 A 项目装 pandas 2.0、B 项目锁死 pandas 1.5 时互相打架。标准做法是:
# 创建虚拟环境 python -m venv ds_env # Windows 激活 ds_env\Scripts\activate # macOS / Linux 激活 source ds_env/bin/activate激活后终端提示符会变成 (ds_env),你在里面 pip install 的任何包都只属于这个项目。依赖一旦冲突,直接删掉这个环境重建,是最省心的后悔药。很多老教程推荐 Anaconda,但 Anaconda 默认环境里包又多又杂,很容易出现“明明能 import,版本却不是想要的那个”的尴尬,所以我更推荐轻量的 venv + pip 组合。
2.2 必装的数据科学库:NumPy、pandas、Matplotlib 与 Scikit-learn 各管一段
数据科学手册里最重要的四个库各司其职:NumPy 管数组和数值计算,pandas 管表格数据的清洗与分析,Matplotlib 管可视化,Scikit-learn 管建模与验证。这四者不是竞争关系,而是流水线的上下游。很多初学者一股脑装几十个包,其实真正高频用到的就这四个。我一般看到一篇数据分析任务,先只装最小集:
pip install numpy pandas matplotlib scikit-learn如果要用 Jupyter Notebook 做交互式探索,再补一个:
pip install jupyter notebook不指定版本时,pip 会按当前 Python 版本拉取最新且兼容的版本。想要固定版本,就明确写出来:
pip install pandas==2.1.0 numpy==1.26.4注意不要同时混用 conda 和 pip,两个包管理器对依赖的解析方式不同,混装之后很容易出现某个库版本不符合预期的问题。我在多个项目里踩过这个坑,后面统一用 pip,冲突率大幅下降。
2.3 用 requirements.txt 固定依赖,让项目换个机器也能重放
手册里的示例跑通是一回事,项目三个月后打开还能跑是另一回事。数据科学项目最容易出现“在我机器上好好的”这种情况,根因就是依赖版本没有锁定。每次项目进入稳定阶段,我都习惯导出一份依赖清单:
pip freeze > requirements.txt以后换电脑或者换环境,一条命令还原:
pip install -r requirements.txt注意:pip freeze 会把当前环境里所有第三方包连同精确版本号写进去,所以这一步必须在虚拟环境里做。如果直接对系统环境执行,会把很多与项目无关的包带进来,恢复时反而增加冲突可能。文件内容大致是 numpy==1.26.4 这种格式,值得提交进版本控制,和代码放在一起,让整个项目具备重放能力。
3. 把手册里的核心用法跑通:NumPy、pandas 与 Matplotlib 最小示例
3.1 NumPy:shape 与广播机制是性能之外的第一课
手册在 NumPy 章节往往先拿 ndarray 与 Python 内置列表做对比。核心差异不只是速度,而是形状(shape)和广播(broadcasting)这两个概念。很多初学者把数组当成列表用,忽略了形状检查,结果在数据对齐时翻车。下面这个例子很典型:
import numpy as np a = np.array([[1], [2], [3]]) # 形状 (3, 1) b = np.array([10, 20, 30, 40]) # 形状 (4,) print(a + b)输出是一个 3 行 4 列的矩阵,每一行分别是 11~41 等计算。逻辑上,NumPy 在执行加法前把 a 横向复制了 4 份,把 b 纵向复制了 3 份,最终两个形状不一致的数组能直接相加。这正是广播机制的价值:它省去了手动写循环对齐维度的工作。
参数说明:shape 属性返回数组各维度大小;reshape 可以改形状,但元素总数必须一致,否则报错。真正理解广播,建议记住一条规则:从最后一个维度向前对齐,两个维度相等,或其中一个为 1,才能广播。如果你遇到 ValueError: operands could not be broadcast together,先回去检查两个数组的 shape。
3.2 pandas:DataFrame 与 Series 的边界,以及 read_csv 的常用参数
pandas 是数据科学手册里篇幅最大的一块。初学者最容易绕晕的就是 DataFrame 和 Series 的区别。一句话解释:DataFrame 是表格,Series 是表格中的一列。读取 CSV 返回的是 DataFrame,取单独一列就变成 Series。先跑通最小读取流程:
import pandas as pd df = pd.read_csv("sales.csv", encoding="utf-8") print(df.head()) print(df["amount"].mean())逻辑说明:read_csv 把文件读成 DataFrame;head() 默认显示前 5 行,避免终端被几万行数据刷屏;df["amount"] 取出量这一列,返回 Series;mean() 求均值。
参数说明:encoding 是最常翻车的参数,Excel 导出的 CSV 常常是 gbk 编码,用 utf-8 读会直接报 UnicodeDecodeError。另一个高频参数是 parse_dates,例如 parse_dates=["date"],能让 pandas 把日期列解析成时间类型,后面按月份分组或画时间序列图会顺手很多。如果文件里日期格式不标准,还可以搭配 format="%Y/%m/%d" 指定输入格式,解析速度也会更快。
3.3 Matplotlib:面向对象绘图是手册主推的写法
很多入门教程画折线图都写成 plt.plot(x, y),然后 plt.show()。这套全局状态接口对快速出图很方便,但一旦画子图、共享坐标轴、调整单个图刻度,全局模式就会到处翻车。数据科学手册通常更推荐面向对象风格:先创建 Figure 和 Axes,再在 Axes 上绘图。
import matplotlib.pyplot as plt # 生成 1 行 2 列的子图 fig, axes = plt.subplots(1, 2, figsize=(10, 4)) axes[0].plot(df["date"], df["amount"]) axes[0].set_title("amount trend") axes[0].tick_params(axis="x", rotation=45) axes[1].hist(df["amount"], bins=30) axes[1].set_title("amount distribution") plt.tight_layout() plt.show()逻辑说明:subplots(1, 2) 创建一个 1 行 2 列的子图容器,axes 是长度为 2 的对象数组。每个 axes 独立控制自己的标题、刻度和坐标轴标签。tick_params 里 rotation=45 让日期标签旋转 45 度,避免横坐标重叠。tight_layout 自动调整子图间距,防止标题和刻度互相遮挡。
参数说明:figsize=(10, 4) 以英寸为单位,适合日常报告;如果投稿或打印,保存时用 plt.savefig("out.png", dpi=150) 提升清晰度。对新手而言,核心习惯是:能用 ax 就用 ax,少用 plt 的全局方法,后面排版才能灵活起来。
4. Python 数据科学常见问题排查:编码、环境、内存与可视化坑
4.1 pip 安装报“externally managed environment”:系统和项目环境打架
现象:在较新的 Linux 发行版里直接执行 pip install numpy,终端报错提示当前环境由系统包管理器管理,不允许外部安装。
原因:Python 社区为了阻止用户把包装进系统 Python 从而破坏系统组件,主动加了保护。
解决:先创建虚拟环境,再在虚拟环境里安装。如果临时绕过保护参数能装上,但下次系统更新时依赖很可能被打乱,不建议用。这个报错在 Windows 上不常见,主要在 Ubuntu 23.04 之后的系统 Python 上出现。
4.2 read_csv 报 UnicodeDecodeError:先看文件头,再选编码
现象:pd.read_csv("sales.csv") 直接报 UnicodeDecodeError,代码看起来没有问题。
原因:文件实际编码不是 utf-8。中文 Windows 环境下,Excel 导出的 CSV 常用 gbk 或 gb2312。
解决:先检查文件头字节,再决定编码参数:
with open("sales.csv", "rb") as f: raw = f.read(20) print(raw)如果头两个字节是 ff fe,说明是 UTF-16;如果出现中文对应的高位字节,多半是 gbk。然后改成 pd.read_csv("sales.csv", encoding="gbk") 即可。这个坑在多人协作、文件来源混杂的项目里几乎必踩。
4.3 画图横坐标标签挤成一团:先调刻度,再考虑降采样
现象:时间跨度大时,Matplotlib 默认给每个数据点都生成一个刻度,几十个日期标签挤在几英寸宽的图里,完全看不清。
原因:默认刻度策略没考虑你的横轴密度。
解决:先调整刻度间隔:
import matplotlib.dates as mdates locator = mdates.DayLocator(interval=7) # 每 7 天一个主刻度 ax.xaxis.set_major_locator(locator)如果你用的是普通字符串坐标,可以先将字符串转成数值位置再画图,然后用 ax.set_xticklabels(rotation=45, ha="right") 旋转标签。记住:坐标密集通常不是数据问题,而是显示问题,别急着把数据给筛了。
4.4 明明改了代码,结果却一模一样:先查 kernel 和环境
现象:在 Jupyter Notebook 里改完单元格并重新运行,输出与上次完全没有区别。
原因:最常见是 Notebook 的 kernel 没有重启,或者那个单元格依赖的中间变量没有重新计算;另一种情况是你在虚拟环境 A 里改代码,但终端激活的是环境 B。
解决:按顺序排查:先重启 kernel 并 Run All,确认每个单元格都执行过;再在脚本里加一段数据形状打印,确认数据真的重新读取了;最后检查终端提示符,当前环境到底是不是你预期的那一个。这个问题的隐蔽性很强,我连续两次把时间花在改模型参数上,最后发现 kernel 里跑的是旧版本代码。
4.5 pandas 读取上亿行 CSV 卡死:用 chunksize 或 usecols 减负
现象:一个几个 GB 的 CSV 文件,pd.read_csv 直接读,内存占用飙升,程序卡死。
原因:read_csv 会把整份文件载入内存,pandas 在后续操作中还会产生多份临时拷贝,内存很容易吃满。
解决:按块读取或只读需要的列:
chunk_iter = pd.read_csv("big.csv", chunksize=100_000, usecols=["amount", "date"]) for chunk in chunk_iter: # 对每个块做聚合,再合并结果 chunk_summary = chunk.groupby("date")["amount"].sum() summaries.append(chunk_summary)逻辑说明:chunksize=100_000 让 pandas 每次只读 10 万行;usecols 只取后续分析需要的列,大幅减少内存占用量。分批聚合后再合并,能支撑超过内存大小的文件分析。关键取舍是:先问自己分析任务是否真的需要全量数据,很多统计场景在分块后结果几乎不变。
5. 从手册走向自己项目:把数据科学流程做成一条可复用的流水线
5.1 数据清洗先写函数:缺失值、重复值与类型转换一次做完
手册里的示例数据大多是规整的,真实场景不是这样。我带项目时的习惯是:拿到任何数据,先写一个 clean 函数,把缺失值、重复行、类型转换这些脏活集中在里面,而不是在每个分析步骤里反复处理。
import pandas as pd def clean_data(df): df = df.drop_duplicates() df["date"] = pd.to_datetime(df["date"], errors="coerce") df["amount"] = ( df["amount"] .astype(str) .str.replace(",", "") .str.replace("¥", "") .astype(float) ) return df.dropna(subset=["amount"])逻辑说明:drop_duplicates 默认保留第一条重复记录;to_datetime 加 errors="coerce",让无法解析的日期变成 NaT 而不是抛异常,这是处理脏数据的关键策略;金额列先转字符串,用 str.replace 清掉千分位逗号和人民币符号,再转 float。dropna(subset=["amount"]) 只删除金额为空的行,不会误伤其他字段。
参数说明:如果日期列里有多种格式,先统一转成 ISO 字符串格式,再交给 to_datetime,解析效率更高。此外我常加一条 assert 做质量关卡:
assert df["date"].isnull().sum() == 0, "日期列还有缺失"这种断言在 Notebook 里看着多余,但放进定时任务或交给同事时,能第一时间暴露清洗逻辑的问题。
5.2 特征工程与模型验证:先切分再训练,固定随机种子
数据科学手册的末尾一般会进入 Scikit-learn。落地时很多人直接把全量数据喂给模型,再切分测试集,这会造成数据泄漏,测试集指标虚高。标准做法是先切分,再训练:
from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) model = RandomForestRegressor(n_estimators=100, max_depth=None, random_state=42) model.fit(X_train, y_train) pred = model.predict(X_test) print("MAE:", mean_absolute_error(y_test, pred))逻辑说明:train_test_split 按 test_size=0.2 切分,留下 20% 做测试;random_state 固定随机种子,保证每次切分一致,模型结果可以复现。RandomForestRegressor 是随机森林回归器,n_estimators=100 表示训练 100 棵决策树,max_depth=None 让树自然生长到纯叶子节点。MAE 输出平均绝对误差,单位与目标值一致,比 R² 更直观。
参数说明:如果分类任务里各类别样本数差距悬殊,可以在切分时加上 stratify=y 做分层抽样,保证训练集和测试集的类别比例一致。树模型对特征量纲不敏感,可以跳过标准化;但如果后续用线性模型或距离类算法,标准化是必做步骤。
5.3 面向流水线写代码:main 函数与断言让项目活起来
手册教你逐个命令调用,但真实项目里,数据会更新、参数要调整、结果要重新生成。把流程封装成函数,是性价比最高的投资。
def load_and_clean(path): df = pd.read_csv(path, encoding="utf-8") return clean_data(df) def analyze(df): top = df[df["amount"] > df["amount"].quantile(0.9)] return top def main(): df = load_and_clean("sales.csv") assert len(df) > 0, "清洗后数据为空" top_users = analyze(df) print(top_users.shape) top_users.to_csv("top_users.csv", index=False) if __name__ == "__main__": main()逻辑说明:main 函数串起加载、清洗、分析、导出完整流程。quantile(0.9) 取出金额最高的 10% 用户,规则简单且可解释。ifname== "main" 保证脚本被 import 时不会立即执行,只在直接运行时进入主流程。断言 assert len(df) > 0 在数据为空时立刻报错,而不是让后续处理产出空报告。
参数说明:to_csv 里 index=False 避免把 DataFrame 的行索引写进文件。这个阶段不需要写复杂的框架,能让每一步单独调试、能重跑、能进版本控制就够了。后面如果逻辑复杂了,再按模块拆分。
6. 收尾的工作流:Notebook 做探索、脚本做交付,用断言双向验证
探索阶段用 Jupyter Notebook 非常顺手,逐格执行、立刻看到中间结果;但一个月后要重新生成报告时,Notebook 的线性执行顺序就成了负担。我现在的习惯是:先用 Notebook 验证思路和参数,然后通过 nbconvert 把流程转成脚本,跑一遍全流程,再确认输出一致。
jupyter nbconvert --to script analysis.ipynb转出来的 analysis.py 会保留代码内容,但原本在 Notebook 中自动渲染的图表不会显示,要把 plt.show() 或 plt.savefig() 明确写进代码。转换后我会快速扫一遍,把 print 的调试输出整理成日志。
另一个用得越来越多的技巧是给关键环节加断言。Notebook 阶段看似多余的 assert,在脚本化之后能真正守护数据质量。
assert df["amount"].isnull().sum() == 0, "金额列仍有缺失" assert df["date"].dt.year.between(2020, 2024).all(), "日期范围异常"这两条断言把编码、清洗逻辑和数据范围三件事锁在了一起。我的个人教训是:刚开做数据科学项目时,习惯在 Notebook 里一条路写到黑,结果一周后要复现报告,不得不从头点一遍单元格,还发现两个格子之间有隐藏的顺序依赖。后来改成先写脚本、再在 Notebook 里调函数,两边才真正顺畅起来。Notebook 提供灵活,脚本提供确定,搭配断言做双向验证,这条工作流保留下来之后,项目交接和自己回看都不再是玄学。希望帮到你。
本文还有配套的精品资源,点击获取