资讯动态

Python数据分析实战:Pandas环境搭建、数据清洗与代码复现指南

发布时间:2026/10/13 17:14:42 来源:尧图企业网站定制
简介这是与《Python for Data Analysis第二版》配套的官方数据集和练习代码包面向希望系统掌握pandas、NumPy的数据分析初学者和数据分析从业者。资源共209个文件压缩包约40.36MB以txt、csv数据文件为主体附有14个ipynb示例笔记本、py脚本及shp等多格式地理数据基本覆盖原书各章节所需的练习数据与演示代码。目前已有347人学习下载。数据集刻意保留原始格式与字段结构便于读者对照书中内容练习数据导入导出、缺失值处理、合并连接、分组聚合、时间序列分析、统计计算与Matplotlib/Seaborn可视化等核心流程进阶读者还可利用其中脚本和ipynb示例尝试Dask并行计算及与Scikit-learn的集成。整体目录清晰、类型多样帮助读者快速定位所需章节适合边读边练可显著降低复现书中案例的门槛是一份高效、实用的配套学习资料。1. 数据分析的 Python这本经典书的价值不止在“读一遍”提到 python data analysis很多人的第一反应是 Pandas、NumPy 和 Jupyter 三件套但真正难的往往是“拿到一堆不规整的数据怎么按业务问题把它清洗、聚合、画图、给出结论”。这本书的配套数据集和示例代码恰好就是为这个目标生的它不是把 API 一个个讲过去而是每章扔给你一份“半脏”的真实数据让你跟着完整走一遍从读入到输出的流程。适合刚转 Python 的业务分析师也适合想补全数据清洗实战经验的开发。这份资源里最值钱的不是代码而是那几十个按章节组织好的真实数据集——它们比任意捏造的 demo 都更能模拟你上班会碰到的脏活。2. 解构这份资源按章节组织的数据集和三类文件格式这份资源的主体是两部分按章节排布的示例代码文件以及配套的 datasets 数据目录。代码文件大部分是以 notebook.ipynb形式组织的因为书里的思路本身就是一边敲一遍看结果notebook 正好承载这种交互过程。数据目录则是一个独立文件树每个子文件夹对应一道数据题。2.1 拿到手先分清四类文件我解压这份资源后通常会先做一次“户口普查”把文件类型分清楚。常见的大致是下面这四类find . -type f | sed s/.*\.// | sort | uniq -c这条命令的作用是把所有文件的后缀名统计一遍按出现次数排序。执行完你大概会看到四类主力.py、.ipynb、.csv、.txt以及少量.json、.xlsx。这里有个容易被新手忽略的点.ipynb本质上是一个 JSON 文件所以如果你用文本编辑器打开 notebook看到一大坨带缩进的键值结构是完全正常的别以为文件坏了。接下来建议按章节目录逐个核对把每章用到的数据文件列一张清单。我在本地建过一张二维表纵轴是章节号横轴是文件名交叉处标“读入/生成/中间产物”。这样做的最大好处是当你复现某一章卡住时能快速判断是代码逻辑问题还是数据源缺失问题。2.2 三种数据格式的读取差异这些数据集虽然来源各异但存储格式逃不出三种主流CSV、JSON、纯文本表格。读取方式不同踩坑点也完全不同。CSV 是最常见的读取时我一般会显式指定编码和数据类型避免 Pandas 自作主张推断出错误类型import pandas as pd df pd.read_csv( datasets/click_log/actions.csv, encodingutf-8, dtype{user_id: int32, action_type: category}, parse_dates[click_time], ) print(df.dtypes)这段代码里我强调了三个参数。encodingutf-8是解决中文乱码的第一道防线dtype手动指定user_id为整数、action_type为分类类型既省内存又避免 Pandas 把全数字 ID 当成数值后参与无意义运算parse_dates把时间字符串直接解析成datetime64类型后面做时间序列聚合会方便很多。如果不指定dtypePandas 对大数据集会有一次额外的全文件扫描来推断类型那种“读文件卡了几秒”的体验往往就是它造成的。JSON 在书里出现在 API 返回数据的场景。读取时注意嵌套层级import pandas as pd df pd.read_json(datasets/api_sample/events.json, orientrecords) nested pd.json_normalize(df[detail])orientrecords告诉 Pandas 每行是一个 JSON 对象。pd.json_normalize会把嵌套的字段“拍平”例如把detail.address.city展平成detail.address.city这一列。这一步看起来简单但实际工作中至少有一半的 JSON 清洗工作量都花在层级展开上。纯文本表格是第三种常见于从数据库导出的日志文件。这种文件最坑的地方是分隔符不统一可能是空格、制表符或竖线。遇到这种我建议先看一眼原始数据再决定参数head -c 1000 datasets/click_log/raw_log.txt执行后可以看到前 1000 个字符人工确认分隔符和列名之后再用pd.read_csv的sep参数去匹配。书里有些数据集就是这种半结构化格式直接套默认逗号分隔大概率会翻车。2.3 数据集的“脏”是刻意保留的这套资源另一个值得玩味的地方是它的数据不是干净的教科书数据。你会在某些表里发现缺失值、重复记录、不一致的日期格式、混入的脏字符。比如有一份按年份排列的人名数据早几年的记录里性别字段只写F后面几年却写成Female还有一份电影评分数据时间字段有的到秒、有的只到日。这些都是原样保留的。我在复现时第一次遇到这种不一致第一反应是“这书是不是勘误没做完”后来才意识到这是作者刻意为之。数据清洗本来就是分析流程里最耗时的一环如果每份数据都干干净净读者就永远学不会处理真实问题。所以你在复现时不要急着把数据“修好”而是把它当作练习对象用第 7 章的数据清洗函数去处理。3. 环境搭建与第一轮复现把 Pandas 的版本墙先破掉这份资源最大的门槛其实不在代码本身而在环境。书出版时的 Pandas 版本是 0.20.x而现在已经到了 2.xAPI 变动虽然不算天翻地覆但足够让老代码在跑的时候弹几个刺眼的报错。所以在复现之前先花 10 分钟把环境边界摸清楚。3.1 环境准备Python 3 版本和 Pandas 版本的选择我建议直接用当前稳定版的 Python 3.10 以上配合 Pandas 2.x 来跑。理论上这本书的代码在新版本上大多数能直接运行但遇到少数 API 变动需要手动小改我在下一章会列出高频差异点。如果你对老版本没执念不要特意去装 Python 2.7 或 Pandas 0.20那样会引入更多兼容性问题。创建虚拟环境是第一步python -m venv venv_pydata source venv_pydata/bin/activate # Windows 下用 venv_pydata\Scripts\activate pip install pandas numpy matplotlib jupyter这段命令会创建一个独立环境并安装核心依赖。这里有个细节安装顺序上先装 pandas 和 numpy再装 matplotlib是因为 matplotlib 在安装时会检测 numpy 的版本先装 numpy 能省去后续重编译的麻烦。Jupyter 放在最后它会自动识别环境中已经装好的包。如果你已经装过 matplotlib 才发现 numpy 版本不对通常卸载重装一次 matplotlib 就能解决。装好后用一个小脚本验证版本和关键的 API 是否可用import pandas as pd import numpy as np print(Pandas:, pd.__version__) print(NumPy:, np.__version__) print(pd.DataFrame({a: [1, 2]}).head())这一步属于“确认基线”。Pandas 2.x 会打印2.0.x之类的版本号只要不低于 2.0 就行。如果版本过低后面某些针对 2.0 的新语法会报错。3.2 把书的第一个核心操作复现一遍环境就绪后我建议先跑一个最小闭环不要一上来就整章复现。选一个你熟悉的数据集做一次 3 步操作读入、筛选、聚合。以那份按年份命名的婴儿姓名数据为例import pandas as pd df pd.read_csv(datasets/baby_names/yob2010.txt, headerNone, names[name, gender, count]) print(df.shape) df_grouped df.groupby(gender)[count].sum() print(df_grouped)这段代码非常朴素但已经把 Pandas 最核心的groupby聚合逻辑走了一遍。pd.read_csv的三个参数里headerNone告诉 Pandas 这个文件没有表头第一行就是数据names手动指定列名这几列的实际含义就是“姓名、性别、当年出生人数”。后面groupby(gender)[count].sum()的语义是按性别分组把每组内的count列求和。跑通这个闭环后你基本就能适应这份资源的代码风格了。这本书里的主要操作基本都是围绕DataFrame的筛选、聚合、合并、透视来展开的你只要熟悉了loc、iloc、groupby、merge这四个核心动作后面的章节会顺利很多。3.3 用真实数据集跑一次可视化验证复现不能只看控制台输出最好画一次图让结果在视觉上说得通。书里有一章讲数据可视化我复现时习惯把聚合结果直接画成柱状图import matplotlib.pyplot as plt df_grouped.plot(kindbar, titleBaby births by gender) plt.ylabel(total count) plt.show()这里值得一提的坑是如果出现Figure窗口一闪而过或者没有显示图形多半是 matplotlib 的后端选成了非交互式的Agg。解决办法是在代码开头写成import matplotlib matplotlib.use(TkAgg) # 或 QtAgg取决于你装了哪个 GUI 后端这一行放在import pyplot之前才有效原因解释一下matplotlib 在导入pyplot时就确定了后端你之后再改是没有用的。4. 复现高频问题排查5 个卡住过我的真实翻车点下面是这份资源里最难缠的 5 个问题我按“现象 → 原因 → 解决”的顺序写每一条都是亲手踩过的坑。4.1 现象.append()方法直接报AttributeError用旧书里的代码把两个 DataFrame 拼接结果在 Pandas 2.x 上报AttributeError: DataFrame object has no attribute append。原因Pandas 2.0 正式移除了append方法这是 1.4.0 版本标记弃用之后的结果。旧书中早期版本会用到这种写法。解决统一改为pd.concat它在 0.20 到 2.x 全系列都存在而且语义更清晰。# 旧写法df1.append(df2) # 新写法 df pd.concat([df1, df2], ignore_indexTrue)ignore_indexTrue的作用是忽略原 DataFrame 的索引重新生成连续的 0..n-1 索引避免拼接后出现重复索引。如果你拼接的是按时间排序的日志通常加上这个参数才是符合预期的行为。4.2 现象数据集路径读取失败FileNotFoundError常见得令人怀疑人生从 git 上下载资源后在 notebook 里直接运行pd.read_csv(datasets/xx.csv)报错找不到文件但文件明明存在。原因notebook 的工作目录不一定是你解压项目的根目录。如果你先启动了 Jupyter 再通过“打开”按钮进入文件夹工作目录通常是 Jupyter 的启动目录如果你用命令行cd进了某个目录再启动工作目录才是那个目录。这个差异在初学者眼里非常像“玄学”其实就一行命令能看清。解决在 notebook 里先执行pwd看当前目录或直接改成绝对路径import os base_path os.path.abspath(os.path.dirname(__file__)) # notebook 下是当前目录 df pd.read_csv(os.path.join(base_path, datasets, click_log, actions.csv))这里有个更实用的土办法把项目根目录添加到sys.path再通过一个模块级常量读取全局路径这样后面所有章节的代码都能复用同一份路径配置。我通常会写一个paths.py# paths.py import os ROOT_DIR os.path.dirname(os.path.abspath(__file__)) DATA_DIR os.path.join(ROOT_DIR, datasets)4.3 现象中文列名显示为乱码或读入后所有中文变成“”文件是 UTF-8 编码但read_csv读进来之后中文全部变成乱码或打印出来是????。原因两个层面。其一是read_csv没有指定encoding而系统默认编码在 Windows 上通常是gbk用 GBK 去读 UTF-8 文件自然乱码其二是终端或 notebook 的显示编码问题如果读取是对的但打印乱码那问题在输出端而不在输入端。解决读取时明确指定编码如果文件本身就是 GBK则把utf-8换成gb18030。我的习惯是写一个小检测函数先试编码再读取def read_csv_auto(path): for enc in [utf-8, gb18030, latin1]: try: return pd.read_csv(path, encodingenc) except UnicodeDecodeError: continue raise ValueError(f无法自动识别编码: {path})这个函数会依次尝试三种常见编码直到找到能完整解码的那一个。latin1是万能兜底因为它对任何字节都不报错代价是中文会变成乱码所以只适合用来保住数据不崩。4.4 现象时间列被读成字符串plot出来的横轴顺序是乱的数据里的日期列读进来是object类型画时间序列图时 X 轴不按时间排序而是按字典序排列。原因Pandas 没有把字符串解析为datetime64导致时序操作全部失效。解决在read_csv时用parse_dates直接指定时间列或在读取后手动转换df[date] pd.to_datetime(df[date], format%Y-%m-%d)这里我要强调format参数的价值。如果不指定格式to_datetime会走自动解析速度慢且有时会猜错。明确%Y-%m-%d之后解析速度会提升一个量级尤其适合几百万行的大文件。4.5 现象读大文件导致内存直接吃满机器卡死读取一份几 GB 的 CSVread_csv执行后内存占用飙升电脑风扇狂转甚至直接死机。原因Pandas 的read_csv默认会把整个文件读进内存对大文件本身就可能超出物理内存再加上给每列推断类型时会有额外的内存开销翻车概率很高。解决分块读取或显式指定列类型。下面这段代码演示了分块处理每 10 万行一批chunk_iter pd.read_csv(datasets/large_log.csv, chunksize100_000) counts 0 for chunk in chunk_iter: counts chunk[user_id].nunique() print(去重用户数量:, counts)chunksize让read_csv返回一个迭代器每一批只占一小块内存。这个方法适合做粗粒度的统计分析但要注意nunique()在每个分块内分别去重不能跨块去重所以上面的计数只是一个近似值。如果你需要精确去重应该改用 SQL 之类的工具或者用polars这类列式引擎这已经超出这本书的讨论范围。5. 进阶用法把示例代码重构成自己的分析脚手架复现一遍之后你可能会发现一个尴尬书里的代码是跑通了但自己换一份数据就不知道怎么改了。我建议做一次“从复现到重构”的升级——把散落在 notebook 里的代码提取成函数形成你自己的分析脚手架。这步做完这份资源才算真正被吸收。以最常用的“读入 清洗 聚合 画图”为例def analyze_click_data(path, date_colclick_time): df pd.read_csv(path, parse_dates[date_col]) df df.dropna(subset[date_col]) df[date_only] df[date_col].dt.date daily_count df.groupby(date_only).size() return daily_count提炼成函数的价值在于notebook 里的代码是“线性叙事”而函数是“逻辑封装”。你换一份数据只需改参数不用改逻辑。我后来在做自己的月度报表时就是把这个模式替换成pd.Grouper(freqM)做按月重采样十分钟就能从原始日志得到一张干净的统计表。进阶的第二层是“保存分析检查点”。我每次跑完聚合都会把中间结果存成.parquet或.feather格式而不是 CSV。原因只有一点这两种格式保留了数据类型和压缩读写速度快得多。import pandas as pd df pd.read_csv(datasets/large_log.csv) df.to_parquet(checkpoints/daily_count.parquet, compressionsnappy) reloaded pd.read_parquet(checkpoints/daily_count.parquet)to_parquet需要安装pyarrow或fastparquet作为底层引擎。我一般优先用pyarrow兼容性更稳。把中间结果存成 parquet 后之后的调试就不用每次都重新读原始大文件这能省下大量等待时间。说到教训我想起早前做模拟项目 X 时为了图省事直接拿一个几百 MB 的原始 CSV 反复read_csv了二十多次每次等半分钟一晚上时间全耗在读盘上。从那以后我养成了一个习惯任何超过一次使用的数据第一次读进来就存成 parquet后续全部从检查点读取。这套思路其实就是把这本经典书的示例逻辑往前推了一步——书教你的是一套分析流程你自己要做的是把流程固化成顺手好用的工具链。希望这份资源能帮你少走点弯路早点跑通你自己的第一条完整分析链路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑