57 绘制散点图
57.1 引言相关性的可视化
散点图(Scatter Plot)是展示两个变量关系最直观的工具。在金融分析中,散点图帮助我们: - 识别相关性:正相关、负相关、无相关 - 发现模式:线性、非线性、聚类 - 检测异常值:远离主群体的数据点 - 验证假设:风险与收益、规模与回报的关系
57.2 散点图的数学基础
散点图展示两个变量 \((X, Y)\) 的关系: \[ \{(x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)\} \]
相关系数(Pearson): \[ \rho_{XY} = \frac{\sum(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum(x_i - \bar{x})^2}\sqrt{\sum(y_i - \bar{y})^2}} \]
相关性的视觉特征: - \(\rho \approx 1\): 点从左下到右上,直线上升 - \(\rho \approx -1\): 点从左上到右下,直线下降 - \(\rho \approx 0\): 点散乱,无明显方向
57.3 基础散点图
平台任务解答代码
以下代码与教学平台任务要求完全一致:
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#任务一
import pandas as pd
index_closeprice = pd.read_excel("https://huoran.oss-cn-shenzhen.aliyuncs.com/1726722771060.xlsx") #导入数据
index_closeprice["日期"] = pd.to_datetime(index_closeprice["日期"] , format='%Y%m%d') # 转换为日期时间格式
index_closeprice.set_index("日期",inplace=True) # 将日期列设为index_closeprice数据框的索引
index_return = index_closeprice/index_closeprice.shift(1)-1 #计算股指的周涨跌幅
index_return = index_return.dropna() #删除缺失值
print(index_return.corr()) #计算指数周涨跌幅的相关系数
#任务二
import matplotlib.pyplot as plt
import pandas as pd # 导入Pandas数据分析库
plt.rcParams['font.sans-serif']=['SimHei'] # 用黑体显示中文
plt.rcParams['axes.unicode_minus']=False # 正常显示负号
index_closeprice = pd.read_excel("https://huoran.oss-cn-shenzhen.aliyuncs.com/1726722771060.xlsx") #导入数据
index_closeprice["日期"] = pd.to_datetime(index_closeprice["日期"] , format='%Y%m%d') # 转换为日期时间格式
index_closeprice.set_index("日期",inplace=True) # 将日期列设为index_closeprice数据框的索引
index_return = index_closeprice/index_closeprice.shift(1)-1 #计算股指的周涨跌幅
index_return = index_return.dropna() #删除缺失值
plt.figure(figsize=(11,6)) # 创建图形画布
plt.subplot(1,2,1) #第1行、第1列子图
plt.scatter(x=index_return.iloc[:,-1],y=index_return.iloc[:,0],c="c",marker="o") #创业板指与上证综指的散点图
plt.xlabel(u"创业板指",fontsize=13) # 设置X轴标签
plt.ylabel(u"上证综指",fontsize=13,rotation=90) # 设置Y轴标签
plt.xticks(fontsize=13) # 设置X轴刻度标签
plt.yticks(fontsize=13) # 设置Y轴刻度标签
plt.title(u"创业板指与上证综指的散点图",fontsize=15) # 设置图表标题
plt.grid(True) # 显示网格线
plt.subplot(1,2,2,sharex=plt.subplot(1,2,1),sharey=plt.subplot(1,2,1)) #与第一个子图共用X轴和Y轴
plt.scatter(x=index_return.iloc[:,-1],y=index_return.iloc[:,1],c="c",marker="o") # 绑制散点图
plt.xlabel(u"创业板指",fontsize=13) # 设置X轴标签
plt.ylabel(u"深证成指",fontsize=13,rotation=90) # 设置Y轴标签
plt.xticks(fontsize=13) # 设置X轴刻度标签
plt.yticks(fontsize=13) # 设置Y轴刻度标签
plt.title(u"创业板指与深证成指的散点图",fontsize=15) # 设置图表标题
plt.grid(True) # 显示网格线
plt.savefig("1.png") # 保存图形至文件# =============================================================================
# 题目: 基础散点图——风险与收益的关系
# =============================================================================
# 本代码展示如何绘制基础散点图,可视化金融学中风险与收益的正相关关系
# 包含数据生成、散点绘制、趋势线拟合和相关系数计算
# ==================== 导入必要的库 ====================
import matplotlib.pyplot as plt # 绘图库
import pandas as pd # 数据分析库
import numpy as np # 数值计算库
# ==================== 设置中文字体 ====================
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置中文字体为黑体,解决中文显示问题
plt.rcParams['axes.unicode_minus'] = False # 解决负号'-'显示为方块的问题
# ==================== 创建风险-收益数据 ====================
np.random.seed(42) # 设置随机种子,确保结果可复现
n_stocks = 50 # 股票数量
# 模拟:风险越高,收益越高(正相关)
risk = np.random.uniform(0.1, 0.4, n_stocks) # 生成50个0.1到0.4之间的均匀分布随机数,代表标准差(风险)
return_mean = 0.03 + 0.5 * risk + np.random.normal(0, 0.02, n_stocks) # 期望收益 = 3%基础收益 + 0.5×风险 + 随机噪声
# ==================== 绘制散点图 ====================
plt.figure(figsize=(10, 6)) # 创建画布,宽度10英寸,高度6英寸,适合学术展示
plt.scatter(risk, return_mean, s=100, alpha=0.7, color='#2E86AB', edgecolors='white')
# s=100: 点的大小(面积),适合多数场景
# alpha=0.7: 透明度0.7,重叠点仍可见
# color='#2E86AB': 蓝色,专业的学术配色
# edgecolors='white': 点边缘为白色,使重叠点更清晰
# ==================== 添加拟合线 ====================
z = np.polyfit(risk, return_mean, 1) # 1阶多项式拟合(线性回归),返回[斜率,截距]
p = np.poly1d(z) # 将拟合系数转换为多项式函数,便于计算
plt.plot(risk, p(risk), 'r--', linewidth=2, label=f'拟合线: y={z[0]:.2f}x+{z[1]:.3f}')
# 'r--': 红色虚线
# linewidth=2: 线宽2像素,清晰可见
# label: 图例标签,显示回归方程
# ==================== 添加坐标轴标签和标题 ====================
plt.xlabel('风险(标准差)', fontsize=12) # X轴标签,字体大小12
plt.ylabel('期望收益率', fontsize=12) # Y轴标签,字体大小12
plt.title('风险与收益的关系', fontsize=16, fontweight='bold') # 标题,字体大小16,加粗
plt.legend(fontsize=11) # 显示图例,字体大小11
plt.grid(True, alpha=0.3) # 添加网格,透明度0.3,不喧宾夺主
plt.tight_layout() # 自动调整布局,防止标签被截断
plt.show() # 显示图形
# ==================== 计算相关系数 ====================
correlation = np.corrcoef(risk, return_mean)[0, 1] # 计算Pearson相关系数,[0,1]取非对角线元素
print(f'风险与收益的相关系数: {correlation:.4f}') # 打印相关系数,保留4位小数
print(f'解释: 正相关,风险越高收益越高') # 解释相关系数的含义scatter关键参数: - s: 点大小,s=100适合大多数场景 - alpha: 透明度,重叠点可见 - color: 点颜色 - edgecolors: 点边缘颜色,'white'使点更清晰
57.4 多组散点图对比
# =============================================================================
# 题目: 多组散点图——不同行业公司的对比
# =============================================================================
# 本代码展示如何在同一散点图中绘制多组数据,使用不同颜色和图例区分
# 应用于金融场景:对比不同行业的风险-收益特征
# ==================== 创建三个行业的数据 ====================
industries = {
'银行': {'risk': np.random.uniform(0.1, 0.2, 15), # 银行业风险较低,10%-20%标准差
'return': np.random.normal(0.04, 0.01, 15)}, # 收益率4%,波动1%
'科技': {'risk': np.random.uniform(0.25, 0.45, 15), # 科技业风险较高,25%-45%标准差
'return': np.random.normal(0.08, 0.02, 15)}, # 收益率8%,波动2%
'公用事业': {'risk': np.random.uniform(0.08, 0.15, 15), # 公用事业风险最低,8%-15%标准差
'return': np.random.normal(0.03, 0.008, 15)} # 收益率3%,波动0.8%
}
# ==================== 定义各行业的颜色 ====================
colors = {'银行': '#E3120B', '科技': '#008080', '公用事业': '#F0A700'}
# 使用高对比度配色方案,便于区分
# ==================== 绘制多组散点图 ====================
plt.figure(figsize=(10, 6)) # 创建画布
for industry, data in industries.items(): # 遍历每个行业
plt.scatter(data['risk'], data['return'], # 绘制散点
s=120, alpha=0.7, color=colors[industry], # 点大小120,透明度0.7,对应颜色
edgecolors='white', label=industry, # 白色边缘,标签为行业名
linewidths=1.5) # 边缘线宽1.5
# ==================== 添加坐标轴标签和标题 ====================
plt.xlabel('风险(标准差)', fontsize=12) # X轴标签
plt.ylabel('收益率', fontsize=12) # Y轴标签
plt.title('不同行业风险-收益特征', fontsize=16, fontweight='bold') # 标题
plt.legend(fontsize=11, loc='upper left') # 图例,位置左上角
plt.grid(True, alpha=0.3) # 网格
plt.tight_layout() # 调整布局
plt.show() # 显示
# ==================== 计算各行业统计 ====================
print('各行业统计:') # 打印标题
for industry, data in industries.items(): # 遍历每个行业
avg_risk = data['risk'].mean() # 计算平均风险
avg_return = data['return'].mean() # 计算平均收益
sharpe = avg_return / avg_risk # 计算简化的夏普比率 = 收益/风险
print(f'{industry}: 风险={avg_risk:.3f}, 收益={avg_return:.3f}, 夏普比率={sharpe:.2f}')
# 打印各行业的统计指标,保留3位小数可视化策略: 1. 颜色区分:每个类别用不同颜色 2. 图例清晰:标注每个颜色的含义 3. 点大小一致`:便于比较密度 4. 边缘线**:使重叠点更清晰
57.5 气泡图
# =============================================================================
# 题目: 气泡图——三维数据展示
# =============================================================================
# 本代码展示如何绘制气泡图,在散点图基础上用气泡大小表示第三维数据
# 应用于金融场景:同时展示风险、收益、市值三个维度
# ==================== 创建三维数据(风险、收益、市值) ====================
n = 30 # 公司数量
data = pd.DataFrame({ # 创建DataFrame存储数据
'风险': np.random.uniform(0.1, 0.4, n), # 风险:10%-40%标准差
'收益': np.random.normal(0.05, 0.02, n), # 收益:均值5%,标准差2%
'市值': np.random.uniform(50, 500, n) # 市值:50-500亿元
})
# ==================== 绘制气泡图 ====================
plt.figure(figsize=(10, 6)) # 创建画布
scatter = plt.scatter(data['风险'], data['收益'], # 绘制散点
s=data['市值']/2, # 气泡大小 = 市值/2,避免过大
c=data['市值'], # 颜色也映射市值,双重编码
cmap='Blues', # 使用Blues色阶,浅蓝到深蓝
alpha=0.6, # 透明度0.6
edgecolors='white', # 白色边缘
linewidths=1.5) # 边缘线宽1.5
# ==================== 添加颜色条 ====================
cbar = plt.colorbar(scatter) # 添加颜色条,显示颜色与市值的映射关系
cbar.set_label('市值(亿元)', fontsize=11) # 设置颜色条标签
# ==================== 添加标签(标注市值最大的3个公司) ====================
top3 = data.nlargest(3, '市值') # 找出市值最大的3家公司
for idx, row in top3.iterrows(): # 遍历这3家公司
plt.annotate(f'市值{row["市值"]:.0f}亿', # 添加标注文本,显示市值
(row['风险'], row['收益']), # 标注位置
xytext=(5, 5), textcoords='offset points', # 文本偏移5个点
fontsize=9, bbox=dict(boxstyle='round,pad=0.3', # 圆角边框
facecolor='yellow', alpha=0.3)) # 黄色背景,透明度0.3
# ==================== 添加标题和标签 ====================
plt.xlabel('风险(标准差)', fontsize=12) # X轴标签
plt.ylabel('收益率', fontsize=12) # Y轴标签
plt.title('风险-收益-市值关系', fontsize=16, fontweight='bold') # 标题
plt.grid(True, alpha=0.3) # 网格
plt.tight_layout() # 调整布局
plt.show() # 显示
print('市值最大的3家公司:') # 打印标题
print(top3) # 打印市值最大的3家公司数据气泡图的设计要点: - 第三维度:气泡大小表示第三个变量 - 大小比例:避免气泡过大遮挡,过小看不见 - 颜色映射:可用颜色强化第三维信息 - 标注:只标注关键点,避免拥挤
57.6 散点图矩阵
# =============================================================================
# 题目: 散点图矩阵——多变量关系探索
# =============================================================================
# 本代码展示如何绘制散点图矩阵,快速探索多个变量两两之间的关系
# 应用于金融场景:分析PE、PB、ROE等多个财务指标的相关性
# ==================== 创建多变量数据 ====================
from pandas.plotting import scatter_matrix # 导入散点图矩阵函数
df_multi = pd.DataFrame({ # 创建包含多个财务指标的DataFrame
'PE': np.random.uniform(10, 60, 100), # 市盈率:10-60倍
'PB': np.random.uniform(0.5, 10, 100), # 市净率:0.5-10倍
'ROE': np.random.uniform(0.05, 0.35, 100), # 净资产收益率:5%-35%
'收益率': np.random.normal(0.05, 0.02, 100) # 收益率:均值5%,标准差2%
})
# ==================== 绘制散点图矩阵 ====================
fig = plt.figure(figsize=(12, 12)) # 创建12×12英寸的画布,适合显示4×4矩阵
axes = scatter_matrix(df_multi, alpha=0.6, diagonal='kde', # 绘制散点图矩阵
c='#2E86AB', edgecolors='white', # 蓝色点,白色边缘
figsize=(12, 12))
# alpha=0.6: 透明度
# diagonal='kde': 对角线显示核密度估计图,展示变量分布
# ==================== 调整布局 ====================
plt.suptitle('多变量散点图矩阵', fontsize=16, fontweight='bold', y=1.02) # 总标题
# y=1.02: 标题位置略高于1,避免重叠
plt.tight_layout() # 自动调整布局
plt.show() # 显示
# ==================== 计算相关系数矩阵 ====================
print('相关系数矩阵:') # 打印标题
print(df_multi.corr().round(3)) # 计算并打印相关系数矩阵,保留3位小数
# .corr()计算Pearson相关系数矩阵散点图矩阵的应用: - 探索性数据分析(EDA):快速发现变量关系 - 特征选择:识别高度相关的特征 - 多元正态性检验:联合分布是否为多元正态
57.7 回归线与置信区间
# =============================================================================
# 题目: 散点图与回归线——包含置信区间
# =============================================================================
# 本代码展示如何绘制带回归线和置信区间的散点图
# 应用于金融场景:验证两个变量之间的线性关系,评估拟合优度
# ==================== 导入seaborn库 ====================
import seaborn as sns # seaborn是基于matplotlib的统计绘图库
# ==================== 创建数据 ====================
np.random.seed(42) # 设置随机种子
x = np.random.uniform(0, 10, 100) # X变量:0到10之间的均匀分布,100个样本
y = 2 + 1.5 * x + np.random.normal(0, 2, 100) # Y变量 = 2 + 1.5×X + 噪声
# ==================== 绘制带回归线的散点图 ====================
plt.figure(figsize=(10, 6)) # 创建画布
sns.regplot(x=x, y=y, # 绘制带回归线的散点图
scatter_kws={'s': 80, 'alpha': 0.6, 'color': '#2E86AB'}, # 散点参数:大小80,透明度0.6,蓝色
line_kws={'color': '#E3120B', 'linewidth': 2.5}, # 回归线参数:红色,线宽2.5
ci=95) # 95%置信区间,半透明阴影显示
# ==================== 添加标签和标题 ====================
plt.xlabel('X变量', fontsize=12) # X轴标签
plt.ylabel('Y变量', fontsize=12) # Y轴标签
plt.title('线性回归与置信区间', fontsize=16, fontweight='bold') # 标题
plt.grid(True, alpha=0.3) # 网格
plt.tight_layout() # 调整布局
plt.show() # 显示
# ==================== 计算回归统计 ====================
from scipy import stats # 导入scipy的统计模块
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
# 线性回归,返回:斜率、截距、相关系数、p值、标准误差
print(f'回归方程: y = {slope:.2f}x + {intercept:.2f}') # 打印回归方程
print(f'R² = {r_value**2:.4f}') # 打印R平方(决定系数)
print(f'p值 = {p_value:.4e}') # 打印p值(科学计数法)
print(f'结论: {"线性关系显著" if p_value < 0.05 else "线性关系不显著"}')
# 如果p值<0.05,则线性关系显著置信区间的含义: - 95%置信区间:有95%的把握真实回归线在此区间内 - 形状:两端较宽(数据少时不确定性大),中间较窄 - 金融应用:预测区间、风险度量
57.8 金融应用CAPM模型
# =============================================================================
# 题目: 证券特征线——CAPM模型可视化
# =============================================================================
# 本代码展示如何可视化CAPM(资本资产定价模型)的证券特征线
# 应用于金融场景:计算股票的Beta和Alpha,评估系统性风险
# ==================== 模拟市场收益率和个股收益率 ====================
n_obs = 60 # 观测期数量(60个交易日,约3个月)
market_return = np.random.normal(0.0008, 0.015, n_obs) # 市场收益率:均值0.08%,标准差1.5%
beta = 1.2 # 个股Beta系数,衡量对市场波动的敏感度
alpha = 0.0002 # Alpha(超额收益),0.02%每天
stock_return = alpha + beta * market_return + np.random.normal(0, 0.01, n_obs)
# 个股收益率 = Alpha + Beta×市场收益率 + 特质风险
# ==================== 绘制证券特征线 ====================
plt.figure(figsize=(10, 6)) # 创建画布
plt.scatter(market_return, stock_return, # 绘制散点
s=80, alpha=0.6, color='#2E86AB', edgecolors='white') # 点大小80,蓝色,白色边缘
# ==================== 添加拟合线(SML) ====================
z = np.polyfit(market_return, stock_return, 1) # 1阶多项式拟合
p = np.poly1d(z) # 转换为多项式函数
x_line = np.linspace(market_return.min(), market_return.max(), 100)
# 生成100个X值,用于绘制平滑的拟合线
plt.plot(x_line, p(x_line), 'r-', linewidth=2.5, label='证券特征线(SML)')
# 绘制拟合线,红色实线
# ==================== 添加理论线(CAPM预测,假设alpha=0) ====================
plt.plot(x_line, beta * x_line, 'g--', linewidth=2, alpha=0.7, label='理论线(α=0)')
# 绘制理论线(经过原点,斜率为Beta),绿色虚线
# ==================== 添加坐标轴标签和标题 ====================
plt.xlabel('市场收益率 $R_m$', fontsize=12) # X轴标签,使用LaTeX公式
plt.ylabel('股票收益率 $R_i$', fontsize=12) # Y轴标签,使用LaTeX公式
plt.title(f'CAPM模型: β={beta:.2f}, α={alpha:.4f}', fontsize=16, fontweight='bold') # 标题显示参数
plt.legend(fontsize=11) # 图例
plt.grid(True, alpha=0.3) # 网格
plt.axhline(y=0, color='k', linestyle='-', linewidth=0.5) # 添加Y=0水平线,黑色
plt.axvline(x=0, color='k', linestyle='-', linewidth=0.5) # 添加X=0垂直线,黑色
plt.tight_layout() # 调整布局
plt.show() # 显示
# ==================== 计算统计量 ====================
correlation = np.corrcoef(market_return, stock_return)[0, 1] # 相关系数
r_squared = correlation ** 2 # R平方(决定系数)
print(f'CAPM统计:') # 打印标题
print(f'Beta (β): {beta:.2f}') # 打印Beta
print(f'Alpha (α): {alpha:.4f}') # 打印Alpha
print(f'R²: {r_squared:.4f}') # 打印R平方
print(f'解释: Beta>{1:.1f},股票波动大于市场') # 解释Beta含义
# Beta>1表示股票波动性大于市场(进攻型)
# Beta<1表示股票波动性小于市场(防御型)