上一期我们学会了用爬虫从网上抓数据。但抓下来的数据如果只是堆在那里,没有任何意义——我们需要分析它、理解它、用图表让它"说话"。
这就是本期的主题:**数据分析**。
我们将学习 Python 数据分析的三大神器:
| 工具 | 作用 | 一句话概括 |
|------|------|------------|
| **NumPy** | 数值计算基础 | 超级快的数组运算 |
| **Pandas** | 数据处理与分析 | 表格操作的瑞士军刀 |
| **Matplotlib** | 数据可视化 | 让数据开口说话 |
>**前置知识**:本教程假设你已经掌握了前面几期学过的基础语法(变量、函数、循环、列表/字典)。如果你还没看过之前的 Episode,建议从 Episode 01 开始。
---
## 6.1 为什么学数据分析?
先回答一个根本问题:**数据分析有什么用?**
举几个现实中的例子:
- 电商分析:哪些商品卖得最好?用户最喜欢在什么时间下单?
- 金融分析:某支股票最近三个月的走势是怎样的?风险和收益如何平衡?
- 社交媒体:哪个话题的讨论量最大?哪些博主影响力最高?
- 科研分析:实验数据有没有显著差异?结论可靠吗?
Python 之所以成为数据分析的首选语言,是因为:
1.**免费且开源**——不需要买昂贵的商业软件
2.**生态强大**——NumPy、Pandas、Matplotlib 构成了完整的数据分析链条
3.**上手简单**——几十行代码就能完成别人几千行才能完成的事
---
## 6.2 NumPy:数值计算的基石
### 6.2.1 什么是 NumPy?
NumPy 是 Python 数值计算的基础库。它的核心是一个叫做 **ndarray** 的 N 维数组对象。
为什么要用 ndarray 而不是普通的 Python 列表?
因为 **ndarray 快得多**——它在底层用 C 语言实现,支持向量化运算,不需要写 for 循环就能对整个数组进行计算。
### 6.2.2 安装和基本使用
```bash
pipinstallnumpy
```
```python
import numpy as np
# 创建一个简单的数组
scores = np.array([85, 92, 78, 95, 88])
print(scores)
# [85 92 78 95 88]
# 基本统计
print(f"平均分: {scores.mean()}") # 87.6
print(f"最高分: {scores.max()}") # 95
print(f"最低分: {scores.min()}") # 78
print(f"标准差: {scores.std():.2f}") # 6.14
```
### 6.2.3 向量化运算——告别 for 循环
这是 NumPy 最强大的特性之一。
```python
import numpy as np
# 假设每个学生期末加分5分
scores = np.array([85, 92, 78, 95, 88])
new_scores = scores + 5
print(new_scores)
# [90 97 83 100 93]
# 乘法也能向量化
prices = np.array([10, 20, 30, 40, 50])
quantities = np.array([2, 3, 1, 4, 2])
total = prices * quantities
print(total)
# [ 20 60 30 160 100]
print(f"总计: {total.sum()}") # 总计: 370
```
**关键点**:你对整个数组做了一次运算,NumPy 在后台自动并行处理。如果用原生 Python 列表,你得写一个 `for` 循环。
### 6.2.4 数组形状变换
```python
import numpy as np
# 10 个学生,每 5 个一组
data = np.arange(10)
print(data)
# [0 1 2 3 4 5 6 7 8 9]
# 变成 2 行 5 列的矩阵
matrix = data.reshape(2, 5)
print(matrix)
# [[0 1 2 3 4]
# [5 6 7 8 9]]
# 变成 5 行 2 列
matrix2 = data.reshape(5, 2)
print(matrix2)
# [[0 1]
# [2 3]
# [4 5]
# [6 7]
# [8 9]]
```
---
## 6.3 Pandas:数据处理瑞士军刀
### 6.3.1 什么是 Pandas?
如果说 NumPy 是数据分析的基石,那么 **Pandas 就是大厦的主体结构**。
Pandas 提供了两种核心数据结构:
| 结构 | 类比 | 说明 |
|------|------|------|
| **Series** | 一列数据 | 带索引的单列数据 |
| **DataFrame** | 一张表格 | 多列数据的组合,类似 Excel 表格 |
### 6.3.2 安装和创建 DataFrame
```bash
pipinstallpandasmatplotlib
```
```python
import pandas as pd
# 方法一:从字典创建
data = {
"name": ["张三", "李四", "王五", "赵六", "钱七"],
"age": [25, 30, 22, 28, 24],
"salary": [8000, 12000, 6000, 15000, 9500],
"department": ["技术部", "市场部", "技术部", "市场部", "人事部"]
}
df = pd.DataFrame(data)
print(df)
```
输出:
```
name age salary department
0 张三 25 8000 技术部
1 李四 30 12000 市场部
2 王五 22 6000 技术部
3 赵六 28 15000 市场部
4 钱七 24 9500 人事部
```
### 6.3.3 查看和筛选数据
```python
import pandas as pd
# 创建示例数据
df = pd.DataFrame({
"product": ["苹果", "香蕉", "橙子", "苹果", "香蕉", "橙子"],
"price": [5.5, 3.0, 4.5, 5.5, 3.2, 4.8],
"quantity": [10, 20, 15, 8, 25, 12],
"month": ["一月", "一月", "一月", "二月", "二月", "二月"]
})
# 1. 查看前几行
print(df.head(3))
# 2. 查看基本信息
print(df.info())
# 3. 筛选条件
print("\n--- 价格大于 4.5 的商品 ---")
print(df[df["price"] > 4.5])
print("\n--- 二月的数据 ---")
print(df[df["month"] == "二月"])
# 4. 多条件筛选
print("\n--- 苹果且 quantity > 8 ---")
print(df[(df["product"] == "苹果") & (df["quantity"] > 8)])
```
### 6.3.4 数据聚合与分组
这是 Pandas 最实用的功能之一——**GROUP BY**。
```python
import pandas as pd
df = pd.DataFrame({
"department": ["技术部", "市场部", "技术部", "市场部", "人事部", "技术部"],
"salary": [15000, 12000, 18000, 10000, 8000, 20000],
"years": [3, 5, 2, 7, 1, 6]
})
# 按部门分组,求平均工资
avg_salary = df.groupby("department")["salary"].mean()
print("各部门平均薪资:")
print(avg_salary)
# department
# 技术部 17666.67
# 市场部 11000.00
# 人事部 8000.00
# 多维度聚合:每个部门的平均薪资、最高薪、最低薪、人数
summary = df.groupby("department")["salary"].agg(["mean", "max", "min", "count"])
summary.columns = ["平均薪资", "最高薪", "最低薪", "人数"]
print("\n部门薪资总结:")
print(summary)
```
输出:
```
部门薪资总结:
平均薪资 最高薪 最低薪 人数
department
技术部 17666.67 20000 15000 3
市场部 11000.00 12000 10000 2
人事部 8000.00 8000 8000 1
```
### 6.3.5 实战:分析电商销售数据
我们来做一个完整的数据分析案例。
假设我们有一份电商订单数据:
```python
import pandas as pd
import numpy as np
# 生成模拟数据
np.random.seed(42)
n_orders = 1000
orders = pd.DataFrame({
"order_id": range(1, n_orders + 1),
"customer_id": np.random.randint(1, 200, n_orders),
"product_category": np.random.choice(["电子产品", "服装", "食品", "图书", "家居"], n_orders),
"amount": np.round(np.random.uniform(10, 2000, n_orders), 2),
"rating": np.random.choice([1, 2, 3, 4, 5], n_orders, p=[0.05, 0.1, 0.15, 0.35, 0.35]),
"is_returned": np.random.choice([0, 1], n_orders, p=[0.85, 0.15])
})
# 1. 总体概况
print("=" * 40)
print("📊 电商订单数据分析报告")
print("=" * 40)
print(f"总订单数: {len(orders)}")
print(f"总金额: ¥{orders['amount'].sum():,.2f}")
print(f"平均订单金额: ¥{orders['amount'].mean():.2f}")
print(f"平均评分: {orders['rating'].mean():.2f}/5")
print(f"退货率: {orders['is_returned'].mean()*100:.1f}%")
# 2. 按类别分析
print("\n--- 各类别销售统计 ---")
category_stats = orders.groupby("product_category").agg(
订单数=("order_id", "count"),
总金额=("amount", "sum"),
平均金额=("amount", "mean"),
平均评分=("rating", "mean"),
退货率=("is_returned", "mean")
)
category_stats["平均评分"] = category_stats["平均评分"].round(2)
category_stats["退货率"] = (category_stats["退货率"] * 100).round(1)
print(category_stats)
# 3. 按金额分段统计
print("\n--- 订单金额分段 ---")
orders["amount_bin"] = pd.cut(orders["amount"], bins=[0, 100, 500, 1000, 2000],
labels=["¥0-100", "¥100-500", "¥500-1000", "¥1000+"])
print(orders["amount_bin"].value_counts().sort_index())
# 4. 高价值客户分析(消费最多的 10%)
top_customer = orders.groupby("customer_id")["amount"].sum().nlargest(20)
print(f"\n--- 高价值客户 TOP 10 ---")
for cid, total in top_customer.head(10).items():
print(f" 客户 #{cid}: ¥{total:,.2f}")
```
这份分析展示了 Pandas 的核心能力:**读取数据 → 筛选分组 → 聚合统计 → 得出结论**。
---
## 6.4 Matplotlib:让数据开口说话
### 6.4.1 为什么需要可视化?
一个数字告诉你的远不如一张图。
> "一幅图胜过一千个字。" —— 这不只是谚语,这是数据分析的黄金法则。
### 6.4.2 折线图——展示趋势
```python
import matplotlib.pyplot as plt
# 模拟一个月的日销售额
days = range(1, 31)
sales = [12000, 13500, 11000, 14200, 15000, 12800, 13600, 14800, 16000, 15200,
13000, 14500, 15800, 17000, 16500, 14000, 13500, 15200, 16800, 17500,
18000, 16200, 15500, 17000, 18500, 19000, 17800, 16500, 17200, 18800]
plt.figure(figsize=(12, 5))
plt.plot(days, sales, marker='o', markersize=3, linewidth=1.5, color='#2196F3')
plt.title('6月份每日销售额趋势', fontsize=14, fontweight='bold')
plt.xlabel('日期', fontsize=12)
plt.ylabel('销售额 (元)', fontsize=12)
plt.xticks(range(1, 31, 3)) # 每3天一个刻度
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('sales_trend.png', dpi=100)
plt.show()
```
### 6.4.3 柱状图——对比分类数据
```python
import matplotlib.pyplot as plt
categories = ["电子产品", "服装", "食品", "图书", "家居"]
total_sales = [450000, 320000, 280000, 150000, 210000]
avg_rating = [4.2, 4.5, 4.8, 4.1, 4.3]
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 左图:销售额柱状图
colors = ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF']
bars = axes[0].bar(categories, total_sales, color=colors, edgecolor='#333', linewidth=0.5)
axes[0].set_title('各类别总销售额', fontsize=13)
axes[0].set_ylabel('销售额 (元)')
for bar, val inzip(bars, total_sales):
axes[0].text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5000,
f'¥{val:,}', ha='center', fontsize=9)
# 右图:评分柱状图
axes[1].bar(categories, avg_rating, color='#4CAF50', edgecolor='#333', linewidth=0.5)
axes[1].set_title('各类别平均评分', fontsize=13)
axes[1].set_ylabel('评分')
axes[1].set_ylim(0, 5)
for bar, val inzip(axes[1].containers[0], avg_rating):
axes[1].text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.03,
f'{val:.1f}', ha='center', fontsize=9)
plt.tight_layout()
plt.savefig('category_comparison.png', dpi=100)
plt.show()
```
### 6.4.4 饼图——展示占比
```python
import matplotlib.pyplot as plt
categories = ["电子产品", "服装", "食品", "图书", "家居"]
sales = [450000, 320000, 280000, 150000, 210000]
colors = ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF']
plt.figure(figsize=(8, 6))
wedges, texts, autotexts = plt.pie(sales, labels=categories, autopct='%1.1f%%',
colors=colors, startangle=90, textprops={'fontsize': 11})
for autotext in autotexts:
autotext.set_fontweight('bold')
autotext.set_color('white')
plt.title('各类别销售占比', fontsize=14, fontweight='bold')
plt.axis('equal')
plt.tight_layout()
plt.savefig('pie_chart.png', dpi=100)
plt.show()
```
### 6.4.5 散点图——探索相关性
```python
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(42)
# 模拟广告投入与销售额的关系
ad_spend = np.random.uniform(10, 100, 50) # 广告投入(万元)
sales_revenue = ad_spend * 5.2 + np.random.normal(0, 80, 50) # 销售额(万元)
# 加一点正相关噪音
plt.figure(figsize=(8, 6))
plt.scatter(ad_spend, sales_revenue, c='#2196F3', s=60, alpha=0.7, edgecolors='#333', linewidth=0.5)
# 添加趋势线
z = np.polyfit(ad_spend, sales_revenue, 1)
p = np.poly1d(z)
plt.plot(ad_spend, p(ad_spend), "--r", linewidth=2, label=f'趋势线: y={z[0]:.1f}x+{z[1]:.1f}')
plt.xlabel('广告投入 (万元)', fontsize=12)
plt.ylabel('销售额 (万元)', fontsize=12)
plt.title('广告投入 vs 销售额', fontsize=14, fontweight='bold')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
print(f"广告投入与销售额的相关系数: {np.corrcoef(ad_spend, sales_revenue)[0, 1]:.3f}")
```
---
## 6.5 综合实战:一份完整的分析报告
我们把前面学到的所有内容整合起来,做一份完整的报告。
```python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei'] # 支持中文显示
plt.rcParams['axes.unicode_minus'] = False
# ========== 1. 创建模拟数据 ==========
np.random.seed(42)
data = {
"student_id": range(1, 101),
"name": [f"学生{i}"for i inrange(1, 101)],
"gender": np.random.choice(["男", "女"], 100),
"math_score": np.random.normal(75, 12, 100).clip(0, 100).round(1),
"english_score": np.random.normal(72, 15, 100).clip(0, 100).round(1),
"cs_score": np.random.normal(80, 10, 100).clip(0, 100).round(1),
"study_hours": np.random.uniform(1, 8, 100).round(1),
"attendance_rate": np.random.uniform(0.5, 1.0, 100).round(2)
}
df = pd.DataFrame(data)
# 修复小数精度
for col in ["math_score", "english_score", "cs_score"]:
df[col] = df[col].clip(0, 100)
# ========== 2. 统计分析 ==========
print("=" * 50)
print("📋 学生成绩分析报告")
print("=" * 50)
print("\n--- 各科成绩统计 ---")
score_cols = ["math_score", "english_score", "cs_score"]
for col in score_cols:
ch_name = {"math_score": "数学", "english_score": "英语", "cs_score": "计算机"}[col]
print(f" {ch_name}: 平均分={df[col].mean():.1f}, "
f"最高={df[col].max():.1f}, "
f"最低={df[col].min():.1f}, "
f"标准差={df[col].std():.1f}")
# 总分
df["total"] = df[score_cols].sum(axis=1)
df["average"] = df["total"] / 3
print(f"\n 总分范围: {df['total'].min():.1f} ~ {df['total'].max():.1f}")
print(f" 平均总分: {df['total'].mean():.1f}")
# 优秀率(≥85分)
excellent_count = (df["average"] >= 85).sum()
print(f" 优秀率: {excellent_count}/{len(df)} = {excellent_count/len(df)*100:.1f}%")
# ========== 3. 相关性分析 ==========
corr_matrix = df[score_cols + ["study_hours", "attendance_rate"]].corr()
print("\n--- 相关性矩阵 ---")
for col in score_cols:
ch_name = {"math_score": "数学", "english_score": "英语", "cs_score": "计算机"}[col]
hrs_corr = corr_matrix.loc[col, "study_hours"]
att_corr = corr_matrix.loc[col, "attendance_rate"]
print(f" {ch_name} vs 学习时长: {hrs_corr:.3f}")
print(f" {ch_name} vs 出勤率: {att_corr:.3f}")
# ========== 4. 可视化 ==========
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 图1: 各科成绩分布直方图
axes[0, 0].hist(df[score_cols], bins=20, alpha=0.6, edgecolor='black', linewidth=0.5,
label=[{"math_score": "数学"}, {"english_score": "英语"}, {"cs_score": "计算机"}][i].get(list(score_cols)[i])
for i inrange(3)])
# 简化版本:直接标注
axes[0, 0].hist(df["math_score"], bins=15, alpha=0.5, label='数学', color='#FF6384', edgecolor='black', linewidth=0.5)
axes[0, 0].hist(df["english_score"], bins=15, alpha=0.5, label='英语', color='#36A2EB', edgecolor='black', linewidth=0.5)
axes[0, 0].hist(df["cs_score"], bins=15, alpha=0.5, label='计算机', color='#4BC0C0', edgecolor='black', linewidth=0.5)
axes[0, 0].set_title('各科成绩分布', fontsize=12)
axes[0, 0].legend()
axes[0, 0].set_xlabel('分数')
axes[0, 0].set_ylabel('人数')
# 图2: 成绩-学习时长散点图
axes[0, 1].scatter(df["study_hours"], df["cs_score"], c='#9966FF', alpha=0.6, s=40, edgecolors='#333', linewidth=0.3)
z = np.polyfit(df["study_hours"], df["cs_score"], 1)
p = np.poly1d(z)
axes[0, 1].plot(df["study_hours"], p(df["study_hours"]), "r--", linewidth=2)
axes[0, 1].set_title('学习时长 vs 计算机成绩', fontsize=12)
axes[0, 1].set_xlabel('每周学习时长 (小时)')
axes[0, 1].set_ylabel('计算机成绩')
# 图3: 性别成绩对比箱线图
df["gender_num"] = df["gender"].map({"男": 0, "女": 1})
gender_labels = ["男生", "女生"]
for i, gender inenumerate(["男", "女"]):
subset = df[df["gender"] == gender]
axes[1, 0].boxplot([subset[c] for c in score_cols], positions=[i * 3 + 1, i * 3 + 2, i * 3 + 3],
widths=0.6, patch_artist=True,
boxprops=dict(facecolor=['#FF6384', '#36A2EB', '#4BC0C0'][j] for j inrange(3)),
medianprops=dict(color='red', linewidth=2))
axes[1, 0].set_xticks([1, 2, 3, 4, 5, 6])
axes[1, 0].set_xticklabels(["男-数学", "男-英语", "男-计算机", "女-数学", "女-英语", "女-计算机"], rotation=30)
axes[1, 0].set_title('男女生成绩对比', fontsize=12)
# 图4: 总分排名 Top 10
top10 = df.nlargest(10, "total")[["name", "total", "average"]]
axes[1, 1].barh(range(10), top10["total"].values, color='#FFCE56', edgecolor='#333', linewidth=0.5)
axes[1, 1].set_yticks(range(10))
axes[1, 1].set_yticklabels(top10["name"].values)
axes[1, 1].set_xlabel('总分')
axes[1, 1].set_title('总分 Top 10')
axes[1, 1].invert_yaxis()
plt.tight_layout()
plt.savefig('student_analysis_report.png', dpi=100, bbox_inches='tight')
plt.show()
print("\n✅ 分析报告已生成,图表已保存为 student_analysis_report.png")
```
---
## 6.6 Pandas 常用操作速查表
在实战中你经常会用到这些操作,把它们记下来:
| 操作 | 代码示例 | 说明 |
|------|---------|------|
| 读取 CSV | `pd.read_csv("file.csv")` | 从文件加载数据 |
| 查看前N行 | `df.head(10)` | 查看前10行 |
| 查看基本信息 | `df.info()` | 数据类型和非空值数量 |
| 统计摘要 | `df.describe()` | 均值、标准差、分位数 |
| 筛选 | `df[df["age"] > 25]` | 按条件过滤 |
| 排序 | `df.sort_values("salary", ascending=False)` | 降序排列 |
| 新增列 | `df["bonus"] = df["salary"] * 0.1` | 计算新列 |
| 删除列 | `df.drop("bonus", axis=1, inplace=True)` | 删除某列 |
| 去重 | `df.drop_duplicates(subset=["name"])` | 按某列去重 |
| 填充缺失值 | `df["age"].fillna(df["age"].mean(), inplace=True)` | 用均值填补缺失 |
| 分组聚合 | `df.groupby("dept")["salary"].mean()` | 按部门分组求平均薪资 |
| 透视表 | `pd.pivot_table(df, values="salary", index="dept", aggfunc="mean")` | 多维统计 |
| 合并表 | `pd.merge(df1, df2, on="key")` | 类似 SQL JOIN |
| 保存结果 | `df.to_csv("output.csv", index=False)` | 导出 CSV |
---
## 6.7 练习题
### 练习 1:个人账单分析
假设你有一个月度支出 CSV 文件 `expenses.csv`,格式如下:
```
date,category,amount,description
2026-06-01,餐饮,85.5,午餐
2026-06-02,交通,6.0,地铁
2026-06-03,购物,299.0,衣服
...
```
请用 Pandas 分析:
1. 每个类别的花费总额和占比
2. 找出开销最大的一个星期
3. 绘制饼图和柱状图
```python
# 参考思路
import pandas as pd
df = pd.read_csv("expenses.csv", parse_dates=["date"])
# 按类别汇总
category_spending = df.groupby("category")["amount"].sum().sort_values(ascending=False)
print(category_spending)
print(category_spending / category_spending.sum() * 100) # 占比
# 按周汇总
df["week"] = df["date"].dt.isocalendar().week
weekly_spending = df.groupby("week")["amount"].sum()
print(f"最大支出周: {weekly_spending.idxmax()}, 金额: ¥{weekly_spending.max():.2f}")
```
### 练习 2:房价数据分析
使用 Pandas 分析一组模拟的房价数据:
```python
import pandas as pd
import numpy as np
np.random.seed(42)
df = pd.DataFrame({
"area": np.random.uniform(50, 200, 200),
"rooms": np.random.choice([1, 2, 3, 4], 200, p=[0.1, 0.3, 0.4, 0.2]),
"distance_to_center": np.random.exponential(10, 200),
"floor": np.random.randint(1, 30, 200),
})
df["price"] = df["area"] * 5 + df["distance_to_center"] * (-0.3) + df["floor"] * 2 + np.random.normal(0, 50, 200)
df["price"] = df["price"].clip(100, 2000)
# 分析:面积、距离市中心远近、楼层对房价的影响
print(df.corr(numeric_only=True)["price"])
```
### 练习 3:构建数据清洗管道
```python
import pandas as pd
import numpy as np
# 模拟一份脏数据
dirty_data = pd.DataFrame({
"name": ["Alice", "", "Charlie", "David", None, "Frank"],
"age": [25, 30, None, 28, -5, 35],
"salary": [5000, 6000, 7000, np.nan, 4000, 8000],
"department": ["技术部", "技术部", "市场部", "市场部", "人事部", "人事部"],
})
# 数据清洗管道
cleaned = dirty_data.copy()
# 1. 删除空名字
cleaned = cleaned[cleaned["name"].notna() & (cleaned["name"] != "")]
# 2. 修正不合理年龄
cleaned = cleaned[(cleaned["age"] > 0) & (cleaned["age"] < 100)]
# 3. 填补缺失薪资
cleaned["salary"].fillna(cleaned.groupby("department")["salary"].transform("mean"), inplace=True)
# 4. 删除缺失年龄的记录
cleaned.dropna(subset=["age"], inplace=True)
print(cleaned)
```
### 练习 4:使用 Seaborn 美化图表
```python
import seaborn as sns
# Seaborn 是基于 Matplotlib 的美化版
sns.set_theme(style="whitegrid")
# 一对多关系的可视化只需一行
sns.pairplot(df[["area", "distance_to_center", "floor", "price"]])
plt.show()
```
### 练习 5:综合实战——分析你的 Spotify 听歌数据
Spotify 可以导出你的听歌历史 CSV。试试用它来做一份分析报告:
- 最爱哪位歌手?
- 最喜欢的歌曲风格(genre)是什么?
- 一天中哪个时段听歌最多?
- 你的 BPM(每分钟节拍数)偏好是多少?
---
## 6.8 本课时知识点小结
| 知识点 | 关键词 |
|--------|--------|
| NumPy 基础 | ndarray / 向量化运算 / reshape / 统计函数 |
| Pandas 核心 | DataFrame / Series / groupby / 筛选 / 聚合 |
| Matplotlib 绘图 | 折线图 / 柱状图 / 饼图 / 散点图 / 箱线图 |
| 数据清洗 | 缺失值处理 / 异常值检测 / 数据类型转换 |
| 相关性分析 | corr() / 散点图 / 趋势线 |
---
## 6.9 工具链总结:三步走
学完这期,你已经掌握了数据分析的完整链路:
```
第05期(爬虫) 第06期(数据分析) 下期(可视化深化)
↓ ↓ ↓
抓取网页数据 → 清洗 + 分析 + 统计 → 深度可视化 + 交互式图表
↓ ↓ ↓
CSV / JSON → Pandas DataFrame → Dashboard / 报告
```
### 你已经会了:
1.**抓取数据**(Episode 05):用 requests + BeautifulSoup 从网上拿数据
2.**组织数据**(Episode 06):用 Pandas DataFrame 管理表格
3.**分析数据**(Episode 06):groupby、agg、相关性
4.**可视化**(Episode 06):用 Matplotlib 画图
---
## 6.10 下期预告
下一期(**Episode 07**),我们要学习 **Web 后端开发——用 FastAPI 搭建自己的 API 服务**。
你将学到:
-**FastAPI**:现代 Python Web 框架,自动生成交互式文档
-**RESTful API**:前后端通信的标准方式
-**数据库集成**:SQLite / PostgreSQL 基础操作
-**实战**:做一个属于自己的"个人记账 API"
届时,你已经可以从网上抓到数据、分析数据、并且通过 API 把数据分享给其他人了。
一套完整的数据管道就打通了。🚀
准备好你的 Python,我们下期见!🐍📊