数据分析全流程实战:Python(Pandas/Matplotlib/Numpy)+ MySQL(附可下载数据源+多图形绘制)
本文聚焦数据分析领域的核心工具链,结合可公开下载的真实数据源,对比Python生态(Pandas/Matplotlib/Numpy)与MySQL在数据处理、分析、可视化环节的差异,通过完整代码示例实现从数据导入、清洗、分析到可视化的全流程,适配数据分析岗位面试/实战需求。
一、前期准备:数据源与环境配置
1. 数据源选择(可公开下载)
选用「国家统计局-2015-2024年全国居民人均可支配收入数据」(可从国家统计局官网或Kaggle下载),数据格式为CSV,核心字段:
| 字段名 | 说明 |
|---|---|
| year | 年份(2015-2024) |
| urban_income | 城镇居民人均可支配收入(元) |
| rural_income | 农村居民人均可支配收入(元) |
| urban_growth | 城镇居民收入同比增长率(%) |
| rural_growth | 农村居民收入同比增长率(%) |
2. 环境配置
bash
# 安装依赖包
pip install pandas numpy matplotlib pymysql sqlalchemy
3. 数据导入MySQL(为后续对比做准备)
python
import pandas as pd
from sqlalchemy import create_engine
# 1. 读取本地CSV数据(数据源下载后放在本地)
df = pd.read_csv("income_data.csv", encoding="utf-8")
# 2. 连接MySQL(需提前创建数据库:data_analysis)
engine = create_engine("mysql+pymysql://root:你的密码@localhost:3306/data_analysis?charset=utf8")
# 3. 将数据写入MySQL表:income_table
df.to_sql(name="income_table", con=engine, if_exists="replace", index=False)
print("数据成功导入MySQL!")
二、核心对比:Python vs MySQL(数据处理+分析)
维度1:数据查询与基础统计
| 分析需求 | MySQL实现 | Python(Pandas/Numpy)实现 | 核心差异 |
|---|---|---|---|
| 1. 查询2020-2024年城镇收入数据 | ```sql | ||
| SELECT year, urban_income | |||
| FROM income_table | |||
| WHERE year BETWEEN 2020 AND 2024; | |||
| ``` | ```python |
读取MySQL数据到DataFrame
df = pd.read_sql("SELECT * FROM income_table", engine)
筛选数据
df_2020_2024 = df[(df["year"] >= 2020) & (df["year"] <= 2024)][["year", "urban_income"]]
print(df_2020_2024)
|
| 2. 计算城乡收入均值/标准差 | ```sql
SELECT
AVG(urban_income) AS urban_avg,
STDDEV(urban_income) AS urban_std,
AVG(rural_income) AS rural_avg,
STDDEV(rural_income) AS rural_std
FROM income_table;
```| ```python
# 均值
urban_avg = np.mean(df["urban_income"])
rural_avg = np.mean(df["rural_income"])
# 标准差
urban_std = np.std(df["urban_income"])
rural_std = np.std(df["rural_income"])
print(f"城镇收入均值:{urban_avg:.2f},标准差:{urban_std:.2f}")
print(f"农村收入均值:{rural_avg:.2f},标准差:{rural_std:.2f}")
```| MySQL内置聚合函数,Numpy计算更高效(大数据量) |
| 3. 计算城乡收入差距 | ```sql
SELECT
year,
(urban_income - rural_income) AS income_gap
FROM income_table;
```| ```python
# 新增列计算收入差距
df["income_gap"] = df["urban_income"] - df["rural_income"]
print(df[["year", "income_gap"]])
```| Python支持列级运算,无需写复杂SQL |
### 维度2:数据清洗(缺失值/异常值处理)
| 清洗需求 | MySQL实现 | Python(Pandas)实现 | 核心差异 |
|----------|-----------|---------------------|----------|
| 1. 处理缺失值(填充均值) | ```sql
-- 先查均值,再更新
UPDATE income_table
SET urban_income = (SELECT AVG(urban_income) FROM income_table)
WHERE urban_income IS NULL;
```| ```python
# 填充缺失值(一行搞定)
df["urban_income"].fillna(df["urban_income"].mean(), inplace=True)
df["rural_income"].fillna(df["rural_income"].mean(), inplace=True)
```| Python更简洁,支持批量操作 |
| 2. 识别异常值(3σ原则) | ```sql
-- MySQL需嵌套多步查询,逻辑复杂
SELECT * FROM income_table
WHERE urban_income > (SELECT AVG(urban_income)+3*STDDEV(urban_income) FROM income_table)
OR urban_income < (SELECT AVG(urban_income)-3*STDDEV(urban_income) FROM income_table);
```| ```python
# 3σ原则识别异常值
def detect_outliers(data):
mean = np.mean(data)
std = np.std(data)
outliers = data[(data > mean + 3*std) | (data < mean - 3*std)]
return outliers
urban_outliers = detect_outliers(df["urban_income"])
print(f"城镇收入异常值:{urban_outliers.values}")
```| Python支持自定义函数,逻辑更清晰 |
## 三、Matplotlib可视化实战(多图形绘制)
基于清洗后的DataFrame,绘制6类核心分析图形,覆盖数据分析面试高频可视化场景:
### 1. 折线图:城乡收入趋势对比
```python
import matplotlib.pyplot as plt
# 设置中文字体(避免乱码)
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 创建画布
plt.figure(figsize=(10, 6))
# 绘制折线
plt.plot(df["year"], df["urban_income"], label="城镇居民收入", color="red", marker="o")
plt.plot(df["year"], df["rural_income"], label="农村居民收入", color="blue", marker="s")
# 添加标签和标题
plt.xlabel("年份")
plt.ylabel("收入(元)")
plt.title("2015-2024年城乡居民人均可支配收入趋势")
plt.legend()
plt.grid(True, alpha=0.3)
# 保存图片
plt.savefig("income_trend.png", dpi=300, bbox_inches="tight")
plt.show()
图形说明:折线图清晰展示收入随年份的变化趋势,可直观看到城乡收入均呈上升趋势,但城镇收入始终高于农村。
2. 柱状图:城乡收入差距对比
python
plt.figure(figsize=(12, 6))
# 绘制柱状图
x = np.arange(len(df["year"]))
width = 0.35
plt.bar(x - width/2, df["urban_income"], width, label="城镇", color="lightcoral")
plt.bar(x + width/2, df["rural_income"], width, label="农村", color="lightskyblue")
# 添加标签
plt.xlabel("年份")
plt.ylabel("收入(元)")
plt.title("2015-2024年城乡居民收入对比")
plt.xticks(x, df["year"])
plt.legend()
plt.grid(axis="y", alpha=0.3)
plt.savefig("income_bar.png", dpi=300, bbox_inches="tight")
plt.show()
图形说明:柱状图对比每年城乡收入绝对值,更易看出收入差距的具体数值。
3. 面积图:收入增长率变化
python
plt.figure(figsize=(10, 6))
# 绘制面积图
plt.fill_between(df["year"], df["urban_growth"], alpha=0.5, color="red", label="城镇增长率")
plt.fill_between(df["year"], df["rural_growth"], alpha=0.5, color="blue", label="农村增长率")
# 添加折线强调趋势
plt.plot(df["year"], df["urban_growth"], color="red", linewidth=1)
plt.plot(df["year"], df["rural_growth"], color="blue", linewidth=1)
plt.xlabel("年份")
plt.ylabel("增长率(%)")
plt.title("2015-2024年城乡收入增长率变化")
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig("growth_area.png", dpi=300, bbox_inches="tight")
plt.show()
图形说明:面积图突出增长率的波动范围,可看到农村收入增长率整体高于城镇。
4. 散点图:收入与增长率的相关性
python
plt.figure(figsize=(8, 6))
# 绘制散点图
plt.scatter(df["urban_income"], df["urban_growth"], color="red", label="城镇", s=50)
plt.scatter(df["rural_income"], df["rural_growth"], color="blue", label="农村", s=50)
plt.xlabel("收入(元)")
plt.ylabel("增长率(%)")
plt.title("收入与增长率相关性")
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig("income_corr.png", dpi=300, bbox_inches="tight")
plt.show()
图形说明:散点图展示收入水平与增长率的相关性,可观察到收入越高,增长率是否呈下降趋势。
5. 饼图:2024年城乡收入占比
python
# 筛选2024年数据
df_2024 = df[df["year"] == 2024]
labels = ["城镇", "农村"]
sizes = [df_2024["urban_income"].values[0], df_2024["rural_income"].values[0]]
colors = ["lightcoral", "lightskyblue"]
explode = (0.05, 0) # 突出城镇部分
plt.figure(figsize=(8, 8))
plt.pie(sizes, explode=explode, labels=labels, colors=colors, autopct="%1.1f%%", shadow=True, startangle=90)
plt.axis("equal") # 保证饼图为正圆形
plt.title("2024年城乡居民收入占比")
plt.savefig("income_pie.png", dpi=300, bbox_inches="tight")
plt.show()
图形说明:饼图展示单一年份的收入结构占比,2024年城镇收入占比约65%以上。
6. 箱线图:收入分布与异常值
python
plt.figure(figsize=(8, 6))
# 绘制箱线图
data = [df["urban_income"], df["rural_income"]]
labels = ["城镇", "农村"]
plt.boxplot(data, labels=labels, patch_artist=True, boxprops={"facecolor": "lightblue"})
plt.xlabel("收入类型")
plt.ylabel("收入(元)")
plt.title("城乡收入分布与异常值")
plt.grid(axis="y", alpha=0.3)
plt.savefig("income_box.png", dpi=300, bbox_inches="tight")
plt.show()
图形说明:箱线图展示收入的四分位数、中位数和异常值,可看到城镇收入的中位数和分布范围均高于农村。
四、核心对比总结(面试必答)
| 工具/场景 | Python(Pandas/Numpy/Matplotlib) | MySQL |
|---|---|---|
| 数据查询 | 灵活,支持复杂条件/多维度筛选 | 高效,擅长结构化查询(WHERE/GROUP BY) |
| 数据清洗 | 简洁,批量操作(缺失值/异常值) | 繁琐,需多步SQL嵌套 |
| 统计分析 | 强大,支持自定义函数/矩阵运算 | 基础,仅内置聚合函数 |
| 可视化 | 一站式实现(多图形绘制) | 无可视化能力,需导出数据后处理 |
| 适用场景 | 数据分析全流程(清洗→分析→可视化) | 数据存储/结构化查询 |
五、面试高频追问与解答
-
Q:为什么数据分析优先用Python而非MySQL?
A:MySQL仅能完成基础的查询和聚合,而Python的Pandas支持复杂的数据清洗、特征工程,Matplotlib可直接可视化,Numpy提升数值计算效率,能覆盖"数据→分析→可视化→报告"全流程,效率远高于MySQL。
-
Q:如何优化大数据量下的Python分析效率?
A:① 用Pandas的
read_sql指定查询条件,只读取需要的数据(避免全表加载);② 用Numpy向量化运算替代循环;③ 分块处理(chunksize)超大CSV/数据库表。 -
Q:Matplotlib绘图时如何解决中文乱码?
A:设置字体参数:
plt.rcParams["font.sans-serif"] = ["SimHei"],plt.rcParams["axes.unicode_minus"] = False。
六、完整代码整合(可直接运行)
python
# 导入依赖
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sqlalchemy import create_engine
# 1. 数据准备
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
# 连接MySQL
engine = create_engine("mysql+pymysql://root:你的密码@localhost:3306/data_analysis?charset=utf8")
# 读取数据
df = pd.read_sql("SELECT * FROM income_table", engine)
# 数据清洗
df["urban_income"].fillna(df["urban_income"].mean(), inplace=True)
df["rural_income"].fillna(df["rural_income"].mean(), inplace=True)
df["income_gap"] = df["urban_income"] - df["rural_income"]
# 2. 基础统计
urban_avg = np.mean(df["urban_income"])
rural_avg = np.mean(df["rural_income"])
print(f"城镇收入均值:{urban_avg:.2f},农村收入均值:{rural_avg:.2f}")
# 3. 可视化
# 3.1 折线图
plt.figure(figsize=(10, 6))
plt.plot(df["year"], df["urban_income"], label="城镇居民收入", color="red", marker="o")
plt.plot(df["year"], df["rural_income"], label="农村居民收入", color="blue", marker="s")
plt.xlabel("年份")
plt.ylabel("收入(元)")
plt.title("2015-2024年城乡居民人均可支配收入趋势")
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig("income_trend.png", dpi=300, bbox_inches="tight")
plt.show()
# 3.2 柱状图
plt.figure(figsize=(12, 6))
x = np.arange(len(df["year"]))
width = 0.35
plt.bar(x - width/2, df["urban_income"], width, label="城镇", color="lightcoral")
plt.bar(x + width/2, df["rural_income"], width, label="农村", color="lightskyblue")
plt.xlabel("年份")
plt.ylabel("收入(元)")
plt.title("2015-2024年城乡居民收入对比")
plt.xticks(x, df["year"])
plt.legend()
plt.grid(axis="y", alpha=0.3)
plt.savefig("income_bar.png", dpi=300, bbox_inches="tight")
plt.show()
# 其他图形代码可按需添加...
总结
- Python生态(Pandas/Numpy/Matplotlib)是数据分析的核心工具,覆盖清洗、分析、可视化全流程,MySQL仅作为数据存储和基础查询工具;
- 可视化需根据分析需求选择图形:趋势用折线图、对比用柱状图、分布用箱线图、占比用饼图;
- 实战中需结合两者优势:用MySQL高效查询数据,用Python完成复杂分析和可视化。