当前位置:首页>python>Python教程 - 数据分析入门:NumPy + Pandas + Matplotlib 实战

Python教程 - 数据分析入门:NumPy + Pandas + Matplotlib 实战

  • 2026-09-08 03:01:26
Python教程 - 数据分析入门:NumPy + Pandas + Matplotlib 实战

上一期我们学会了用爬虫从网上抓数据。但抓下来的数据如果只是堆在那里,没有任何意义——我们需要分析它、理解它、用图表让它"说话"。

这就是本期的主题:**数据分析**。

我们将学习 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,我们下期见!🐍📊

最新文章

随机文章