Module 9: 数据科学核心库
NumPy、Pandas、Matplotlib —— Python 数据分析的三大支柱
本章概览
这是全书最重要的一章!本章将深入学习 Python 数据科学的核心库:NumPy(数值计算)、Pandas(数据处理)、Matplotlib/Seaborn(数据可视化)。掌握这三个库,你就掌握了 Python 数据分析的 80% 核心技能。
重要提示:这一章内容最多(6篇文章),但也最实用。建议预留 2-3 周时间深入学习和实践。
学习目标
学完本章后,你将能够:
- 使用 NumPy 进行高效的数值计算
- 使用 Pandas 读取、清洗、转换数据
- 掌握 Pandas 的分组、合并、透视等高级操作
- 使用 Matplotlib 和 Seaborn 创建专业图表
- 计算描述性统计量
- 使用 Requests 爬取网页数据
- 构建完整的数据分析工作流
章节内容
01 - NumPy 基础
核心问题: 为什么需要 NumPy?
核心内容:
- NumPy 是什么?
- Python 科学计算的基础库
- Pandas 基于 NumPy 构建
- 比 Python 列表快 10-100 倍
- 创建数组:python
import numpy as np # 从列表创建 ages = np.array([25, 30, 35, 40]) # 特殊数组 zeros = np.zeros(5) # [0. 0. 0. 0. 0.] ones = np.ones(5) # [1. 1. 1. 1. 1.] seq = np.arange(0, 10, 2) # [0 2 4 6 8] # 随机数 rand = np.random.rand(5) # 0-1均匀分布 randn = np.random.randn(5) # 标准正态分布 - 数组操作:
- 向量化运算(无需循环)
- 索引和切片
- 统计函数:
mean(),std(),sum(),max() - 线性代数:矩阵乘法、转置
- 对比 R 和 Stata:
- R:
c(1, 2, 3)≈ NumPy 数组 - Stata:
matrix命令 ≈ NumPy
- R:
为什么重要?
- Pandas DataFrame 的底层是 NumPy 数组
- 理解 NumPy 帮助你更好地理解 Pandas
- 数值计算和矩阵运算必备
实际应用:
# 生成模拟数据
np.random.seed(42)
n = 1000
education = np.random.normal(16, 2, n) # 教育年限
income = 30000 + 5000 * education + np.random.normal(0, 10000, n)
# 计算相关系数
correlation = np.corrcoef(education, income)[0, 1]02 - Pandas 入门
核心问题: 如何用 Pandas 处理表格数据?
核心内容:
- Pandas 是什么?
- Python 的"Excel/Stata"
- 核心数据结构:DataFrame(表格)和 Series(列)
- 创建 DataFrame:python
import pandas as pd # 从字典创建 df = pd.DataFrame({ 'age': [25, 30, 35], 'income': [50000, 75000, 85000] }) # 从 CSV 读取 df = pd.read_csv('survey.csv') - 数据查看:
df.head():前几行df.info():数据类型和缺失值df.describe():描述性统计df.shape:行数和列数
- 数据选择:
- 选择列:
df['age']或df[['age', 'income']] - 选择行:
df.loc[0](按标签)、df.iloc[0](按位置) - 条件筛选:
df[df['age'] > 30]
- 选择列:
- 数据操作:
- 新列:
df['log_income'] = np.log(df['income']) - 删除:
df.drop('column', axis=1) - 排序:
df.sort_values('income') - 重命名:
df.rename(columns={'old': 'new'})
- 新列:
对比 Stata/R:
| 操作 | Stata | R | Pandas |
|---|---|---|---|
| 选择列 | keep age income | df[c('age', 'income')] | df[['age', 'income']] |
| 筛选 | keep if age > 30 | df[df$age > 30, ] | df[df['age'] > 30] |
| 新列 | gen log_income = log(income) | df$log_income <- log(df$income) | df['log_income'] = np.log(df['income']) |
03 - Pandas 高级操作
核心问题: 如何进行复杂的数据处理?
核心内容:
- 缺失值处理:python
df.isnull().sum() # 统计缺失值 df.dropna() # 删除缺失值 df.fillna(df.mean()) # 填充均值 - 分组聚合(GroupBy):python
# 按性别分组计算平均收入 df.groupby('gender')['income'].mean() # 多个统计量 df.groupby('gender').agg({ 'income': ['mean', 'std', 'count'], 'age': 'mean' }) - 合并数据:python
# 类似 SQL JOIN df_merged = pd.merge(df1, df2, on='id', how='left') # 纵向合并(追加行) df_combined = pd.concat([df1, df2], ignore_index=True) - 透视表(Pivot Table):python
# 类似 Excel 透视表 pivot = df.pivot_table( values='income', index='gender', columns='education_level', aggfunc='mean' ) - 数据重塑:
melt():宽格式 → 长格式pivot():长格式 → 宽格式
- Apply 和自定义函数:python
df['income_category'] = df['income'].apply( lambda x: '高收入' if x > 80000 else '中低收入' )
对比 Stata:
| 操作 | Stata | Pandas |
|---|---|---|
| 分组统计 | bysort gender: summarize income | df.groupby('gender')['income'].describe() |
| 合并 | merge 1:1 id using other.dta | pd.merge(df1, df2, on='id') |
| 透视 | table gender education, c(mean income) | df.pivot_table(...) |
| 重塑 | reshape | melt() / pivot() |
04 - Matplotlib 与 Seaborn
核心问题: 如何创建专业的数据可视化?
核心内容:
- Matplotlib 基础:python
import matplotlib.pyplot as plt # 散点图 plt.scatter(df['education'], df['income']) plt.xlabel('Education Years') plt.ylabel('Income ($)') plt.title('Education vs Income') plt.show() # 直方图 plt.hist(df['age'], bins=20, edgecolor='black') plt.xlabel('Age') plt.ylabel('Frequency') plt.show() - Seaborn(更美观):python
import seaborn as sns # 散点图 + 回归线 sns.regplot(x='education', y='income', data=df) # 箱线图 sns.boxplot(x='gender', y='income', data=df) # 热力图(相关系数) sns.heatmap(df.corr(), annot=True, cmap='coolwarm') - 常用图表:
- 散点图:变量关系
- 直方图:分布
- 箱线图:组间比较
- 条形图:分类统计
- 线图:时间序列
- 热力图:相关矩阵
- 子图和布局:python
fig, axes = plt.subplots(2, 2, figsize=(12, 10)) axes[0, 0].hist(df['age']) axes[0, 1].scatter(df['education'], df['income'])
对比 Stata/R:
- Stata:
graph twoway scatter,histogram - R:
ggplot2(最强大的可视化库) - Python: Matplotlib(底层) + Seaborn(高层)
05 - 描述性统计
核心问题: 如何计算统计量?
核心内容:
- 单变量统计:python
# 均值、中位数、标准差 df['income'].mean() df['income'].median() df['income'].std() # 分位数 df['income'].quantile([0.25, 0.5, 0.75]) # 完整描述 df['income'].describe() - 分组统计:python
df.groupby('gender')['income'].agg(['mean', 'std', 'count']) - 相关分析:python
# 相关系数矩阵 df[['age', 'education', 'income']].corr() # 两变量相关 df['education'].corr(df['income']) - 频数分布:python
# 频数表 df['gender'].value_counts() # 交叉表 pd.crosstab(df['gender'], df['education_level']) - 使用 scipy.stats:python
from scipy import stats # t 检验 stats.ttest_ind(group1, group2) # 卡方检验 stats.chi2_contingency(crosstab)
对比 Stata:
| 操作 | Stata | Pandas |
|---|---|---|
| 描述统计 | summarize | df.describe() |
| 分组统计 | bysort gender: summarize income | df.groupby('gender')['income'].describe() |
| 相关系数 | correlate income education | df[['income', 'education']].corr() |
| 频数表 | tabulate gender | df['gender'].value_counts() |
06 - 网页爬取入门
核心问题: 如何获取网页数据?
核心内容:
- Requests 库:python
import requests # GET 请求 response = requests.get('https://example.com') print(response.status_code) # 200 表示成功 print(response.text) # HTML 内容 - BeautifulSoup 解析 HTML:python
from bs4 import BeautifulSoup soup = BeautifulSoup(response.text, 'html.parser') # 提取标题 title = soup.find('title').text # 提取所有链接 links = soup.find_all('a') for link in links: print(link.get('href')) - 实战案例:爬取表格数据:python
# 爬取维基百科表格 url = 'https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(nominal)' tables = pd.read_html(url) # 自动提取所有表格 df = tables[0] # 第一个表格 - API 调用:python
# 获取 JSON 数据 response = requests.get('https://api.example.com/data') data = response.json() df = pd.DataFrame(data) - 注意事项:
- 遵守 robots.txt
- 添加延时,避免被封
- 检查网站使用条款
社科应用:
- 爬取新闻文章
- 获取社交媒体数据
- 下载公开数据集
- 调用政府/学术 API
Python vs Stata vs R 数据分析对比
| 任务 | Stata | R | Pandas |
|---|---|---|---|
| 读取数据 | use data.dta | read.csv() | pd.read_csv() |
| 查看数据 | describe | summary() | df.describe() |
| 选择列 | keep age income | df[c('age', 'income')] | df[['age', 'income']] |
| 筛选行 | keep if age > 30 | df[df$age > 30, ] | df[df['age'] > 30] |
| 新列 | gen log_income = log(income) | df$log_income <- log(df$income) | df['log_income'] = np.log(df['income']) |
| 分组统计 | bysort gender: summarize | aggregate() / group_by() | df.groupby().agg() |
| 合并 | merge | merge() | pd.merge() |
| 可视化 | graph | ggplot2 | matplotlib / seaborn |
如何学习本章?
学习路线(2-3 周)
第 1-2 天(4小时): NumPy 基础
- 阅读 01 - NumPy 基础
- 练习数组创建和操作
- 理解向量化运算
第 3-5 天(10小时): Pandas 入门
- 阅读 02 - Pandas 入门
- 练习读取 CSV、筛选、新列
- 完成练习题
第 6-8 天(10小时): Pandas 高级
- 阅读 03 - Pandas 高级操作
- 练习 GroupBy、Merge、Pivot
- 用真实数据集练习
第 9-10 天(6小时): 数据可视化
- 阅读 04 - Matplotlib 与 Seaborn
- 创建各种图表
- 美化图表
第 11 天(3小时): 描述性统计
- 阅读 05 - 描述性统计
- 计算统计量
- 相关分析
第 12 天(3小时): 网页爬取(可选)
- 阅读 06 - 网页爬取入门
- 尝试爬取简单网页
- 调用公开 API
总时间: 36 小时(2-3 周)
最小化学习路径
对于社科学生,绝对核心:
必学(日常分析必备,20小时):
- 02 - Pandas 入门(完整学习)
- 03 - Pandas 高级操作(GroupBy、Merge)
- 04 - Matplotlib 基础(散点图、直方图、箱线图)
- 05 - 描述性统计
重要(提升效率,10小时):
- 01 - NumPy 基础(理解底层)
- Seaborn 可视化
- Pandas 链式调用
可选(特定需求):
- 06 - 网页爬取(需要爬取数据时)
- NumPy 线性代数
- 高级可视化(Plotly 交互图表)
学习建议
边学边练,用真实数据
- 不要只看示例代码
- 下载真实数据集(Kaggle、UCI、政府数据)
- 尝试复现论文的描述性统计表
建立 Pandas 思维方式
python# 循环思维(慢且丑) for i in range(len(df)): if df.loc[i, 'age'] > 30: df.loc[i, 'age_group'] = 'old' # Pandas 思维(快且优雅) df['age_group'] = df['age'].apply(lambda x: 'old' if x > 30 else 'young') # 或者 df['age_group'] = np.where(df['age'] > 30, 'old', 'young')记住常用操作的"惯用法"
python# 读取数据 df = pd.read_csv('data.csv') # 快速查看 df.head() df.info() df.describe() # 数据清洗流水线 df_clean = (df .dropna(subset=['age', 'income']) # 删除缺失值 .query('age >= 18 & age <= 100') # 筛选 .assign(log_income=lambda x: np.log(x['income'])) # 新列 .sort_values('income') # 排序 )实践项目:完整数据分析
python# 项目:收入不等式分析 # 1. 读取数据 df = pd.read_csv('income_survey.csv') # 2. 数据清洗 df_clean = df.dropna().query('age >= 18 & income > 0') # 3. 描述性统计 print(df_clean.describe()) print(df_clean.groupby('gender')['income'].mean()) # 4. 可视化 sns.boxplot(x='education_level', y='income', data=df_clean) sns.histplot(df_clean['income'], bins=50) # 5. 保存结果 df_clean.to_csv('income_clean.csv', index=False)
常见问题
Q: NumPy 和 Pandas 有什么区别? A:
- NumPy:数值计算,适合同质数据(全是数字)
- Pandas:数据处理,适合异质数据(数字+文本)
- Pandas 基于 NumPy 构建
Q: 什么时候用 loc,什么时候用 iloc? A:
loc:按标签(列名、行索引名称)iloc:按位置(0, 1, 2...)
df.loc[0, 'age'] # 第 0 行,'age' 列
df.iloc[0, 1] # 第 0 行,第 1 列Q: 为什么我的 Pandas 代码很慢? A:
- 不要用循环:
for i in range(len(df)) - 用向量化操作:
df['new'] = df['old'] * 2 - 用 apply:
df['new'] = df['old'].apply(func) - 用 NumPy:
df['new'] = np.log(df['old'])
Q: Matplotlib 和 Seaborn 选哪个? A:
- Matplotlib:底层、灵活、复杂
- Seaborn:高层、美观、简单
- 建议:快速探索用 Seaborn,精细调整用 Matplotlib
Q: 如何学习 Pandas?记不住这么多函数! A:
- 不要死记硬背
- 记住核心操作:
read_csv(),head(),query(),groupby(),merge() - 其他的用到时查文档
- 多练习,形成肌肉记忆
下一步
完成本章后,你将掌握:
- NumPy 数值计算和数组操作
- Pandas 数据读取、清洗、转换
- 分组聚合、数据合并、透视表
- Matplotlib/Seaborn 数据可视化
- 描述性统计分析
- 网页数据爬取
在 Module 10 中,我们将学习机器学习和 LLM API 调用,探索更前沿的应用。
在 Module 11 中,我们将学习代码规范、调试和 Git,提升代码质量。
这是最重要的一章!掌握 NumPy 和 Pandas,你就掌握了 Python 数据分析的核心!