查看全课大纲(第 86 / 101 节)
- 1.数据分析基本概念
- 2.学习数据分析的一般路线
- 3.数据分析的流程
- 4.数据类型
- 5.环境部署(1)
- 6.环境部署(2)
- 7.课程介绍
- 8.TXT文件操作
- 9.JSON文件操作
- 10.CSV文件操作
- 11.Excel文件操作
- 12.数据库及SQL常用语法
- 13.数据库基本操作
- 14.数据库多表连接
- 15.实战:欧洲职业足球数据库分析
- 16.爬虫简介
- 17.URL管理模块
- 18.网页下载模块
- 19.网页解析模块(1)
- 20.网页解析模块(2)
- 21.Scrapy简介
- 22.Scrapy使用步骤(1)
- 23.Scrapy使用步骤(2)
- 24.Scrapy使用步骤(3)
- 25.Scrapy使用步骤(4)
- 26.实战:获取国内城市空气质量指数数据
- 27.NumPy和SciPy介绍
- 28.多维数组
- 29.多维数组操作
- 30.NumPy的常用方法
- 31.向量化介绍
- 32.向量化及通用函数
- 33.实战:2016美国大选分析
- 34.数据结构-Series
- 35.数据结构-DataFrame
- 36.数据结构-Index
- 37.Series的索引操作
- 38.DataFrame的索引操作
- 39.索引操作总结
- 40.运算与对齐
- 41.函数应用操作(1) -- map
- 42.函数应用操作 (2) -- apply applymap
- 43.文件读写操作
- 44.排序操作
- 45.数据清洗--处理缺失数据
- 46.数据清洗--处理重复数据
- 47.数据清洗--替换数据
- 48.常用统计方法(1) -- describe quantile
- 49.常用统计方法(2) -- sum mean median count
- 50.常用统计方法(3) -- max min idxmax idxmin
- 51.常用统计方法(4) -- mad var std cumsum
- 52.实战:全球食品数据分析
- 53.层级索引
- 54.分组与聚合介绍
- 55.分组操作(1) -- GroupBy对象及常用聚合操作
- 56.分组操作(2) -- 自定义分组及聚合操作
- 57.透视表介绍
- 58.透视表操作
- 59.数据规整(1) -- 数据合并concat
- 60.数据规整(2) -- 数据连接merge
- 61.数据重构(3) -- 数据重构stack unstack
- 62.实战:互联网电影资料库分析
- 63.探索性数据分析EDA介绍
- 64.EDA的目的
- 65.EDA常用工具
- 66.Matplotlib绘图基本介绍
- 67.Matplotlib画布
- 68.散点图和柱状图的绘制
- 69.直方图的绘制
- 70.矩阵绘图
- 71.子图的使用
- 72.Matplotlib颜色、标记、线型
- 73.Matplotlib坐标刻度、标签、图例、标题
- 74.Seaborn介绍
- 75.数据集分布可视化(1) -- 单变量分布、双变量分布
- 76.数据集分布可视化(2) -- 变量关系可视化
- 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
- 78.交互式数据可视化工具Bokeh介绍
- 79.Bokeh绘制散点图、柱状图、盒子图、弦图
- 80.Bokeh绘制常用图形元素
- 81.3D绘图 -- mplot3d
- 82.3D曲线可视化
- 83.3D散点图可视化
- 84.3D柱状图可视化
- 85.Pandas绘图
- 86.实战:Lending Club借贷数据探索性分析及可视化
- 87.机器学习介绍及应用场景
- 88.机器学习建模介绍 (1) -- 分类
- 89.机器学习建模介绍 (2) -- 回归
- 90.机器学习建模介绍 (3) -- 聚类
- 91.机器学习分类
- 92.机器学习工具scikit-learn
- 93.使用scikit-learn的流程
- 94.数据集准备及划分
- 95.模型选择
- 96.数据预处理及特征工程
- 97.过拟合与欠拟合
- 98.模型调参介绍
- 99.模型调参方法
- 100.模型测试及评价
- 101.实战:通过移动设备行为数据预测性别和年龄
实战:Lending Club借贷数据探索性分析及可视化
约 13 分钟
Lending Club 借贷数据探索性分析及可视化
小象实战讲义 · Python数据分析实战
本节我们将通过一个实战案例,综合运用数据可视化技能,对 Lending Club 借贷数据进行探索性分析(EDA)。我们将学习如何从原始数据出发,通过数据处理、选择合适的可视化工具,最终生成清晰的分析图表,并理解数据背后的业务含义。
💡 核心导读
- 实战目标:对 Lending Club 借贷数据集进行探索性分析,完成借贷金额分析、目的占比分析和变量间关系分析。
- 核心技能:Pandas 数据处理、Matplotlib 与 Seaborn 可视化、EDA 分析流程。
- 项目流程:数据读取与查看 → 数据清洗与规整 → 多维度可视化 → 结果保存与解读。
- 工具生态:了解交互式可视化(如 Bokeh、Plotly)的“数据→图元→浏览器渲染”链路,但本节使用成熟的 Matplotlib/Seaborn 完成静态分析。
- 数据说明:原课使用 Lending Club 2007-2015 年真实借贷数据集,因数据年代较久且规模较大,本节将使用构造的中性模拟数据演示同一套分析方法。
项目背景与任务
Lending Club 是美国一家知名的 P2P 借贷平台。本次分析的数据集模拟了该平台的借贷记录,包含借贷金额、周期、年收入、借贷状态、目的、所在州等信息。
我们的分析任务明确分为三个:
- 借贷金额分析可视化:分析借贷金额在不同维度(如借贷周期、状态、目的、州)下的分布与均值关系。
- 借贷目的占比可视化:查看不同借贷目的在总借贷笔数中的占比情况。
- 变量间关系可视化:探索关键数值变量(如借贷金额与年收入)之间的关系,并考虑按借贷目的进行分组观察。
我们将遵循标准的 EDA 流程:先进行必要的数据处理,然后选择合适的可视化工具(柱状图、饼图、散点图矩阵等)进行绘图,最后保存可视化结果。
数据处理与准备
在开始可视化之前,我们需要对数据进行初步的清洗和规整,以确保分析的有效性和图表的美观性。
import pandas as pd
import matplotlib
matplotlib.use('Agg') # 使用非交互式后端,保证代码在任何环境可运行
import matplotlib.pyplot as plt
import seaborn as sns
# 设置显示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 构造模拟数据
data = {
'loan_amnt': [10000, 15000, 8000, 20000, 12000, 18000, 5000, 22000, 9000, 16000],
'term': ['36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months'],
'annual_inc': [60000, 75000, 50000, 90000, 65000, 80000, 45000, 95000, 55000, 70000],
'loan_status': ['Current', 'Fully Paid', 'Current', 'Late', 'Fully Paid', 'Current', 'Fully Paid', 'Late', 'Current', 'Fully Paid'],
'purpose': ['debt_consolidation', 'credit_card', 'home_improvement', 'debt_consolidation', 'other', 'credit_card', 'home_improvement', 'other', 'debt_consolidation', 'credit_card'],
'addr_state': ['CA', 'NY', 'TX', 'CA', 'FL', 'NY', 'TX', 'CA', 'FL', 'NY']
}
raw_data = pd.DataFrame(data)
print("原始数据预览:")
print(raw_data)
print("\n数据集形状:", raw_data.shape)原始数据预览:
loan_amnt term annual_inc loan_status purpose addr_state
0 10000 36 months 60000 Current debt_consolidation CA
1 15000 60 months 75000 Fully Paid credit_card NY
2 8000 36 months 50000 Current home_improvement TX
3 20000 60 months 90000 Late debt_consolidation CA
4 12000 36 months 65000 Fully Paid other FL
5 18000 60 months 80000 Current credit_card NY
6 5000 36 months 45000 Fully Paid home_improvement TX
7 22000 60 months 95000 Late other CA
8 9000 36 months 55000 Current debt_consolidation FL
9 16000 60 months 70000 Fully Paid credit_card NY
数据集形状: (10, 6)接下来,我们定义一个数据处理函数。主要处理逻辑包括:
- 删除缺失值。
- 聚焦主要借贷目的:对于类别过多的
purpose列,我们只保留出现频率最高的前 N 个类别,其余类别合并为“other”,使可视化结果更清晰。
# 每个代码块自包含:重建模拟数据(与上一块一致)
import pandas as pd
data = {
'loan_amnt': [10000, 15000, 8000, 20000, 12000, 18000, 5000, 22000, 9000, 16000],
'term': ['36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months'],
'annual_inc': [60000, 75000, 50000, 90000, 65000, 80000, 45000, 95000, 55000, 70000],
'loan_status': ['Current', 'Fully Paid', 'Current', 'Late', 'Fully Paid', 'Current', 'Fully Paid', 'Late', 'Current', 'Fully Paid'],
'purpose': ['debt_consolidation', 'credit_card', 'home_improvement', 'debt_consolidation', 'other', 'credit_card', 'home_improvement', 'other', 'debt_consolidation', 'credit_card'],
'addr_state': ['CA', 'NY', 'TX', 'CA', 'FL', 'NY', 'TX', 'CA', 'FL', 'NY']
}
raw_data = pd.DataFrame(data)
def process_data(df):
"""
处理原始数据集。
1. 删除缺失值。
2. 将非 top 的借贷目的归类为 'other'。
"""
# 1. 去掉缺失值
proc_data = df.dropna()
# 2. 选择 top 2 的借贷目的 (因为样本数据少,这里取2)
top_purposes = proc_data['purpose'].value_counts().head(2).index.tolist()
print("Top 2 借贷目的:", top_purposes)
# 3. 将其余的 purposes 替换为 'other'
# ~ 表示取反,即找出不在 top_purposes 中的行索引
non_top_idx = proc_data[~proc_data['purpose'].isin(top_purposes)].index
proc_data.loc[non_top_idx, 'purpose'] = 'other'
print("\n处理后的数据预览(purpose列已规整):")
print(proc_data[['purpose', 'loan_amnt']].head())
return proc_data
proc_data = process_data(raw_data)Top 2 借贷目的: ['debt_consolidation', 'credit_card']
处理后的数据预览(purpose列已规整):
purpose loan_amnt
0 debt_consolidation 10000
1 credit_card 15000
2 other 8000
3 debt_consolidation 20000
4 other 12000任务一:借贷金额分析可视化
我们首先分析借贷金额在不同维度下的平均表现。例如,不同借贷周期的平均金额是多少?不同借贷状态的平均金额有何差异?这有助于我们理解业务模式。
我们将使用柱状图进行对比,因为它非常适合展示不同类别下数值型变量的聚合结果(如均值、总和)。
# 每个代码块自包含:重建经 process_data 规整后的数据(purpose 已合并非 top 类为 other)
import pandas as pd
import matplotlib
matplotlib.use('Agg') # 使用非交互式后端,保证代码在任何环境可运行
import matplotlib.pyplot as plt
proc_data = pd.DataFrame({
'loan_amnt': [10000, 15000, 8000, 20000, 12000, 18000, 5000, 22000, 9000, 16000],
'term': ['36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months'],
'annual_inc': [60000, 75000, 50000, 90000, 65000, 80000, 45000, 95000, 55000, 70000],
'loan_status': ['Current', 'Fully Paid', 'Current', 'Late', 'Fully Paid', 'Current', 'Fully Paid', 'Late', 'Current', 'Fully Paid'],
'purpose': ['debt_consolidation', 'credit_card', 'other', 'debt_consolidation', 'other', 'credit_card', 'other', 'other', 'debt_consolidation', 'credit_card'],
'addr_state': ['CA', 'NY', 'TX', 'CA', 'FL', 'NY', 'TX', 'CA', 'FL', 'NY']
})
def visualise_loan_amnt(df, col_name, title, xlabel):
"""
借贷金额分析可视化通用函数。
按 col_name 分组,计算 loan_amnt 的均值,并绘制柱状图。
"""
# 分组并计算均值
mean_amnt_by_group = df.groupby(col_name)['loan_amnt'].mean()
print(f"\n按 [{col_name}] 分组的平均借贷金额:")
print(mean_amnt_by_group)
# 绘制柱状图
fig, ax = plt.subplots(figsize=(8, 5))
mean_amnt_by_group.plot(kind='bar', ax=ax, title=title)
ax.set_xlabel(xlabel)
ax.set_ylabel('借贷金额(均值)')
plt.tight_layout()
# 实际应用中可在此保存图片:plt.savefig('output.png')
print(f"已生成图表:{title}")
plt.close(fig) # 关闭图形,释放内存
# 分析借贷周期 vs 借贷金额
visualise_loan_amnt(proc_data, 'term', '借贷周期 vs 借贷金额', '借贷周期')
# 分析借贷状态 vs 借贷金额
visualise_loan_amnt(proc_data, 'loan_status', '借贷状态 vs 借贷金额', '借贷状态')按 [term] 分组的平均借贷金额:
term
36 months 8800.0
60 months 18200.0
Name: loan_amnt, dtype: float64
已生成图表:借贷周期 vs 借贷金额
按 [loan_status] 分组的平均借贷金额:
loan_status
Current 11250.0
Fully Paid 12000.0
Late 21000.0
Name: loan_amnt, dtype: float64
已生成图表:借贷状态 vs 借贷金额结果解读:
- 借贷周期:60个月周期的平均借贷金额(18200)远高于36个月周期(8800),符合直觉,长期借贷通常对应更大金额。
- 借贷状态:状态为“Late”(逾期)的平均借贷金额最高(21000),这可能暗示大额借贷的还款压力更大,逾期风险相对更高。“Fully Paid”(已还清,12000)和“Current”(还款中,11250)的平均金额明显更低。
任务二:借贷目的占比可视化
接下来,我们想了解不同借贷目的在总贷款笔数中的分布情况。饼图是展示占比最直观的图表类型。
# 每个代码块自包含:重建经 process_data 规整后的数据
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
proc_data = pd.DataFrame({
'loan_amnt': [10000, 15000, 8000, 20000, 12000, 18000, 5000, 22000, 9000, 16000],
'term': ['36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months'],
'annual_inc': [60000, 75000, 50000, 90000, 65000, 80000, 45000, 95000, 55000, 70000],
'loan_status': ['Current', 'Fully Paid', 'Current', 'Late', 'Fully Paid', 'Current', 'Fully Paid', 'Late', 'Current', 'Fully Paid'],
'purpose': ['debt_consolidation', 'credit_card', 'other', 'debt_consolidation', 'other', 'credit_card', 'other', 'other', 'debt_consolidation', 'credit_card'],
'addr_state': ['CA', 'NY', 'TX', 'CA', 'FL', 'NY', 'TX', 'CA', 'FL', 'NY']
})
def visualise_loan_purpose_percent(purpose_series):
"""
可视化借贷目的比例。
"""
# 计算各目的的计数和百分比
pur_count = purpose_series.value_counts()
pur_per = pur_count / pur_count.sum() * 100 # 计算百分比
print("各借贷目的占比:")
for purpose, percent in pur_per.items():
print(f" {purpose}: {percent:.1f}%")
# 绘制饼图
fig, ax = plt.subplots(figsize=(6, 6))
pur_per.plot(kind='pie', autopct='%1.1f%%', ax=ax, startangle=90)
ax.set_ylabel('') # 隐藏默认的y轴标签
ax.set_title('借贷目的占比')
plt.tight_layout()
print("已生成饼图:借贷目的占比")
plt.close(fig)
visualise_loan_purpose_percent(proc_data['purpose'])各借贷目的占比:
other: 40.0%
debt_consolidation: 30.0%
credit_card: 30.0%
已生成饼图:借贷目的占比结果解读:在我们保留的两个主要目的中,债务合并(debt_consolidation)和信用卡还款(credit_card)各占30%;被合并的非 top 目的统一归为 other,占比40%。在实际分析中,我们可以调整“top N”的数值,以展示更精细的目的分类。
任务三:变量间关系可视化
最后,我们探索两个数值变量之间的关系,并观察这种关系是否因第三个分类变量(借贷目的)的不同而呈现差异。散点图矩阵(PairPlot) 是完成此任务的强大工具,它可以同时展示多个变量两两之间的散点图和对角线上的分布图。
我们将使用 Seaborn 库的 pairplot 函数。
# 每个代码块自包含:重建经 process_data 规整后的数据
import pandas as pd
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import seaborn as sns
proc_data = pd.DataFrame({
'loan_amnt': [10000, 15000, 8000, 20000, 12000, 18000, 5000, 22000, 9000, 16000],
'term': ['36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months', '36 months', '60 months'],
'annual_inc': [60000, 75000, 50000, 90000, 65000, 80000, 45000, 95000, 55000, 70000],
'loan_status': ['Current', 'Fully Paid', 'Current', 'Late', 'Fully Paid', 'Current', 'Fully Paid', 'Late', 'Current', 'Fully Paid'],
'purpose': ['debt_consolidation', 'credit_card', 'other', 'debt_consolidation', 'other', 'credit_card', 'other', 'other', 'debt_consolidation', 'credit_card'],
'addr_state': ['CA', 'NY', 'TX', 'CA', 'FL', 'NY', 'TX', 'CA', 'FL', 'NY']
})
def visualise_relation(df):
"""
变量间关系可视化。
绘制 loan_amnt 和 annual_inc 的散点图矩阵,并按 purpose 着色。
"""
print("正在生成变量间关系图(PairPlot)...")
# 使用 Seaborn 的 pairplot
g = sns.pairplot(df, vars=['loan_amnt', 'annual_inc'], hue='purpose', height=4)
g.fig.suptitle('借贷金额与年收入关系(按目的着色)', y=1.02)
plt.tight_layout()
print("PairPlot 已生成。")
plt.close(g.fig)
visualise_relation(proc_data)正在生成变量间关系图(PairPlot)...
PairPlot 已生成。结果解读:PairPlot 会生成一个2x2的网格。对角线是每个变量(借贷金额、年收入)的核密度估计图(分布)。非对角线是这两个变量之间的散点图,并且点按照 purpose 的不同用颜色区分。通过此图,我们可以初步判断:
- 借贷金额与年收入之间是否存在线性或非线性关联。
- 不同借贷目的的客户,其借贷金额和年收入的分布是否有特征差异。
- 在我们的模拟小数据集中,可能看不出强烈规律,但对于真实大数据,这是发现洞察的关键步骤。
📝 动手练一练
- 概念辨析:在任务一的柱状图分析中,我们使用了
groupby().mean()。如果我想看每个分类下的借贷金额总和而非平均值,应该怎么修改代码?这种“总和”柱状图在什么业务场景下比“均值”图更有用?
👉 点击查看参考答案
修改 visualise_loan_amnt 函数中的聚合计算,将 .mean() 改为 .sum()。
# 每个代码块自包含:构造示例数据演示「求和」版本
import pandas as pd
df = pd.DataFrame({
'addr_state': ['CA', 'NY', 'TX', 'CA', 'FL', 'NY', 'TX', 'CA', 'FL', 'NY'],
'loan_amnt': [10000, 15000, 8000, 20000, 12000, 18000, 5000, 22000, 9000, 16000]
})
col_name = 'addr_state'
sum_amnt_by_group = df.groupby(col_name)['loan_amnt'].sum()
print("各州借贷金额总和:")
print(sum_amnt_by_group)各州借贷金额总和:
addr_state
CA 52000
FL 21000
NY 49000
TX 13000
Name: loan_amnt, dtype: int64业务场景:“总和”图适用于分析整体规模或资源消耗。例如,分析各州的总借贷金额,有助于了解哪些地区是信贷市场的主力,用于制定区域性的营销或风险策略。而“均值”图更侧重于了解典型客户的行为或负担水平。
- 动手实践:在任务二的数据处理部分,我们将非 Top 的借贷目的合并为了“other”。请尝试修改代码,将
top_purposes的数量从2改为3(即保留前3多的目的),然后重新运行任务二的占比分析,观察饼图的变化。
👉 点击查看参考答案
修改 process_data 函数中的一行代码:
# 每个代码块自包含:重建数据演示 head(3) 版本
# (示例数据把原数据第 5 行的 other 改为 medical,避免与 home_improvement 计数并列影响演示)
import pandas as pd
proc_data = pd.DataFrame({
'purpose': ['debt_consolidation', 'credit_card', 'home_improvement', 'debt_consolidation', 'medical',
'credit_card', 'home_improvement', 'other', 'debt_consolidation', 'credit_card'],
'loan_amnt': [10000, 15000, 8000, 20000, 12000, 18000, 5000, 22000, 9000, 16000]
})
# 将 head(2) 改为 head(3)
top_purposes = proc_data['purpose'].value_counts().head(3).index.tolist()
print("Top 3 借贷目的:", top_purposes)
non_top_idx = proc_data[~proc_data['purpose'].isin(top_purposes)].index
proc_data.loc[non_top_idx, 'purpose'] = 'other'
print("\n各借贷目的占比:")
pur_per = proc_data['purpose'].value_counts() / len(proc_data) * 100
for purpose, percent in pur_per.items():
print(f" {purpose}: {percent:.1f}%")Top 3 借贷目的: ['debt_consolidation', 'credit_card', 'home_improvement']
各借贷目的占比:
debt_consolidation: 30.0%
credit_card: 30.0%
home_improvement: 20.0%
other: 20.0%重新运行后,‘other’ 类别的占比会减少,因为更多具体的目的被单独展示出来了。这体现了数据规整中“粒度”的权衡:保留更多类别细节更丰富,但图表可能变得杂乱;合并次要类别使主次分明,但会损失部分信息。
本章小结
本节我们完成了一个完整的数据可视化实战项目,对模拟的借贷数据进行了探索性分析。我们重温了从数据加载、清洗规整到选择合适图表进行多角度可视化的全流程。
📋 行动清单
- 尝试调整代码参数:修改“任务一”中分析的列(例如尝试
addr_state),生成新的柱状图,观察不同州的平均借贷金额差异。 - 练习图表保存:在任一绘图函数的
plt.tight_layout()后添加plt.savefig('你的文件名.png', dpi=300),将生成的图表真正保存到本地。 - 探索更多关系:在“任务三”的
pairplot中,尝试将vars参数增加'term'(需先转换为数值),观察三个变量间的多维关系。
通过这个案例,我们不仅巩固了 Matplotlib 和 Seaborn 的绘图技巧,更重要的是掌握了如何让可视化服务于具体的业务分析问题,从图表中提炼出有意义的结论。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载全套课件打包(第1-5章)ZIP · 12.8MB
- 下载全套课件打包(第6-8章)ZIP · 15MB
- 下载实战数据集:AppleStore 应用商城分析ZIP · 329KB
- 下载实战数据集:女性服装电商分析ZIP · 2.8MB
- 下载Python 数据分析环境搭建指南PDF · 2MB
- 下载Scrapy 安装教程PDF · 12.7MB
- 下载附加实战项目:AppleStore 应用商城数据分析ZIP · 0.3MB · ipynb + CSV 数据
- 下载附加实战项目:银行电话营销数据分析ZIP · 0.4MB · ipynb + CSV 数据
- 下载附加实战项目:女性服装电商评论数据分析ZIP · 2.7MB · ipynb + CSV 数据
- 下载附加实战项目:美国化学学会杂志数据分析ZIP · 34.2MB · ipynb + SQLite 数据库