一、前期准备:数据源与环境配置
1. 数据源选择
选用公开可获取的全国居民人均可支配收入数据,核心字段包括年份、城镇/农村居民收入及增长率。
2. 环境配置
pip install pandas numpy matplotlib pymysql sqlalchemy
3. 数据导入 MySQL
import pandas as pd
from sqlalchemy import create_engine
df = pd.read_csv("income_data.csv", encoding="utf-8")
engine = create_engine("mysql+pymysql://root:你的密码@localhost:3306/data_analysis?charset=utf8")
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 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) ``` | MySQL 擅长结构化查询,Python 支持灵活筛选 | | |
| 2. 计算城乡收入均值/标准差 | sql SELECT AVG(urban_income), STDDEV(urban_income) FROM income_table; | python urban_avg = np.mean(df["urban_income"]) urban_std = np.std(df["urban_income"]) | 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"] | 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) | Python 更简洁,支持批量操作 |
| 2. 识别异常值(3σ原则) | sql SELECT * FROM income_table WHERE urban_income > (SELECT AVG(urban_income)+3*STDDEV(urban_income) FROM income_table); | ```python def detect_outliers(data): mean = np.mean(data) std = np.std(data) return data[(data > mean + 3*std) | (data < mean - 3*std)] ``` |
三、Matplotlib 可视化实战(多图形绘制)
基于清洗后的 DataFrame,绘制 6 类核心分析图形。
1. 折线图:城乡收入趋势对比
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. 柱状图:城乡收入差距对比
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. 面积图:收入增长率变化
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. 散点图:收入与增长率的相关性
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 年城乡收入占比
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()
6. 箱线图:收入分布与异常值
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 提升数值计算效率,能覆盖'数据→分析→可视化→报告'全流程。
- Q:如何优化大数据量下的 Python 分析效率?
A:① 用 Pandas 的
read_sql 指定查询条件;② 用 Numpy 向量化运算替代循环;③ 分块处理(chunksize)超大 CSV/数据库表。
- Q:Matplotlib 绘图时如何解决中文乱码?
A:设置字体参数:
plt.rcParams["font.sans-serif"] = ["SimHei"],plt.rcParams["axes.unicode_minus"] = False。