python day9
·
import pandas as pd # 导入pandas库
import numpy as np #导入numpy库
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore') # 忽略警告信息
data = pd.read_csv(r'E:\PythonStudy\heart.csv')
data.isnull() # 布尔矩阵显示缺失值,这个方法返回一个布尔矩阵,也是dataframe对象,其中True表示是缺失值,False表示不是缺失值。
data.isnull().sum()
data.columns # 所有列名 data的属性
# 特征名中文映射字典(适配心脏病相关临床数据字段)
feature_name_mapping = {
'age': '年龄',
'sex': '性别',
'cp': '胸痛类型', # Chest Pain Type
'trestbps': '静息血压(mm Hg)', # Resting Blood Pressure
'chol': '血清胆固醇(mg/dl)', # Serum Cholesterol
'fbs': '空腹血糖>120mg/dl', # Fasting Blood Sugar
'restecg': '静息心电图结果', # Resting Electrocardiographic Results
'thalach': '最大心率', # Maximum Heart Rate Achieved
'exang': '运动诱发心绞痛', # Exercise Induced Angina
'oldpeak': 'ST段压低(相对于休息状态)', # ST Depression Induced by Exercise Relative to Rest
'slope': 'ST段峰值斜率', # Slope of the Peak Exercise ST Segment
'ca': '荧光检查显示的主要血管数量', # Number of Major Vessels Colored by Fluoroscopy
'thal': '地中海贫血症类型', # Thallium Stress Test Result
'target': '是否患病(目标变量)' # 1=患病, 0=未患病(根据数据常规标注)
}
data_cn = data.rename(columns=feature_name_mapping)
data_cn.head()
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# ---------------------- 1. 定义连续特征列表(与中文映射对应)----------------------
# 基于你指定的连续特征:年龄、静息血压、血清胆固醇、最大心率、ST段压低(相对于休息状态)
# 对应原始字段名(需与DataFrame列名一致)
continuous_features = ['age', 'trestbps', 'chol', 'thalach', 'oldpeak']
# (可选)如果需要中文特征名用于图表标题,可结合之前的映射字典
feature_name_mapping = {
'age': '年龄',
'trestbps': '静息血压(mm Hg)',
'chol': '血清胆固醇(mg/dl)',
'thalach': '最大心率',
'oldpeak': 'ST段压低(相对于休息状态)'
}
# ---------------------- 2. 创建画布和子图(2行3列)----------------------
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文显示问题
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(15, 10)) # 2行3列,设置图表大小
axes = axes.flatten() # 将2x3的二维数组展平为一维数组,方便enumerate遍历
# ---------------------- 3. 用enumerate()遍历连续特征,绘制箱线图----------------------
for idx, feature in enumerate(continuous_features):
# 绘制箱线图(data为你的数据集,需替换为实际DataFrame名称)
data.boxplot(column=feature, ax=axes[idx], patch_artist=True,
boxprops=dict(facecolor='lightblue'), # 箱体颜色
medianprops=dict(color='red')) # 中位数线颜色
# 设置子图标题(使用中文映射名)
axes[idx].set_title(f'{feature_name_mapping[feature]} 箱线图', fontsize=12, fontweight='bold')
# 设置x轴标签(隐藏,因箱线图x轴无多分类)
axes[idx].set_xlabel('')
# 设置y轴标签(使用中文映射名)
axes[idx].set_ylabel(feature_name_mapping[feature], fontsize=10)
# 优化刻度标签大小
axes[idx].tick_params(axis='both', which='major', labelsize=9)
# ---------------------- 4. 隐藏多余的空白子图----------------------
# 连续特征共5个,2行3列共6个子图,需隐藏最后1个(索引5)
for idx in range(len(continuous_features), len(axes)):
axes[idx].set_visible(False)
# ---------------------- 5. 调整子图间距,避免重叠----------------------
plt.tight_layout()
# 显示图表
plt.show()
# (可选)保存图表
# plt.savefig('连续特征箱线图.png', dpi=300, bbox_inches='tight')
# ---------------------- 1. 沿用之前定义的连续特征列表和中文映射(无需重复定义,此处仅为呼应)----------------------
# continuous_features = ['age', 'trestbps', 'chol', 'thalach', 'oldpeak']
# feature_name_mapping 沿用之前的定义
# ---------------------- 2. 创建画布和子图(保持2行3列)----------------------
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文显示问题
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(15, 10))
axes = axes.flatten() # 展平为一维数组,方便enumerate遍历
# ---------------------- 3. 用enumerate()遍历特征,绘制小提琴图----------------------
for idx, feature in enumerate(continuous_features):
# 提取当前特征的数据(替换data为你的数据集名称)
feature_data = data[feature].dropna() # 去除缺失值,避免报错
# 绘制小提琴图(violinplot)
parts = axes[idx].violinplot(feature_data, positions=[0], showmeans=True, showmedians=True)
# 美化小提琴图样式
for pc in parts['bodies']:
pc.set_facecolor('lightcoral') # 琴身颜色
pc.set_edgecolor('darkred') # 琴身边框颜色
pc.set_alpha(0.7) # 透明度
# 突出显示均值和中位数
parts['cmeans'].set_color('darkblue') # 均值线颜色
parts['cmedians'].set_color('gold') # 中位数线颜色
parts['cmeans'].set_linewidth(2)
parts['cmedians'].set_linewidth(2)
# 设置子图标题和标签
axes[idx].set_title(f'{feature_name_mapping[feature]} 小提琴图', fontsize=12, fontweight='bold')
axes[idx].set_xlabel('') # 隐藏x轴标签
axes[idx].set_ylabel(feature_name_mapping[feature], fontsize=10)
axes[idx].tick_params(axis='both', which='major', labelsize=9)
# 调整x轴范围,让小提琴图更居中
axes[idx].set_xlim(-0.5, 0.5)
axes[idx].set_xticks([]) # 隐藏x轴刻度
# ---------------------- 4. 隐藏多余的空白子图----------------------
for idx in range(len(continuous_features), len(axes)):
axes[idx].set_visible(False)
# ---------------------- 5. 调整子图间距,避免重叠----------------------
plt.tight_layout()
# 显示图表
plt.show()
# (可选)保存图表
# plt.savefig('连续特征小提琴图.png', dpi=300, bbox_inches='tight')
# ---------------------- 1. 定义离散特征列表(排除5个连续特征+目标变量)----------------------
# 原始所有特征(参考初始字段列表)
all_features = ['age', 'sex', 'cp', 'trestbps', 'chol', 'fbs', 'restecg',
'thalach', 'exang', 'oldpeak', 'slope', 'ca', 'thal', 'target']
# 已确定的连续特征(5个)
continuous_features = ['age', 'trestbps', 'chol', 'thalach', 'oldpeak']
# 目标变量(标签,排除在特征之外)
target = 'target'
# 离散特征 = 所有特征 - 连续特征 - 目标变量
discrete_features = [feat for feat in all_features if feat not in continuous_features and feat != target]
# (沿用之前的完整中文映射字典,确保离散特征都有对应中文)
feature_name_mapping = {
'age': '年龄',
'sex': '性别',
'cp': '胸痛类型',
'trestbps': '静息血压(mm Hg)',
'chol': '血清胆固醇(mg/dl)',
'fbs': '空腹血糖>120mg/dl',
'restecg': '静息心电图结果',
'thalach': '最大心率',
'exang': '运动诱发心绞痛',
'oldpeak': 'ST段压低(相对于休息状态)',
'slope': 'ST段峰值斜率',
'ca': '荧光检查显示的主要血管数量',
'thal': '地中海贫血症类型',
'target': '是否患病(目标变量)'
}
# ---------------------- 2. 创建画布和子图(2行4列)----------------------
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文显示问题
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题
fig, axes = plt.subplots(nrows=2, ncols=4, figsize=(18, 10)) # 2行4列,适配8个子图位置
axes = axes.flatten() # 展平为一维数组,方便enumerate遍历
# ---------------------- 3. 用enumerate()遍历离散特征,绘制条形图----------------------
for idx, feature in enumerate(discrete_features):
# 统计离散特征各取值的数量(替换data为你的数据集名称)
value_counts = data[feature].value_counts().sort_index() # 按索引排序,保证顺序一致
# 绘制条形图
bars = axes[idx].bar(
x=value_counts.index.astype(str), # x轴为特征取值(转为字符串,避免数值类型误解)
height=value_counts.values,
color='lightseagreen',
edgecolor='darkcyan',
alpha=0.8
)
# 在条形图顶部添加数值标签
for bar in bars:
height = bar.get_height()
axes[idx].text(
bar.get_x() + bar.get_width()/2., # 水平居中
height + 0.1, # 数值在条形上方偏移一点
f'{int(height)}', # 显示计数(整数)
ha='center', va='bottom', fontsize=9
)
# 设置子图标题和标签
axes[idx].set_title(f'{feature_name_mapping[feature]} 分布', fontsize=12, fontweight='bold')
axes[idx].set_xlabel('特征取值', fontsize=10)
axes[idx].set_ylabel('计数', fontsize=10)
axes[idx].tick_params(axis='both', which='major', labelsize=9)
# 调整y轴范围,避免数值标签超出画布
axes[idx].set_ylim(0, max(value_counts.values) * 1.1)
# ---------------------- 4. 隐藏多余的空白子图----------------------
# 离散特征共6个(sex/cp/fbs/restecg/exang/slope/ca/thal?实际计算:13个特征-5连续-1目标=7个?)
# 实际离散特征列表:['sex', 'cp', 'fbs', 'restecg', 'exang', 'slope', 'ca', 'thal'] → 8个,刚好填满2行4列,无需隐藏
# (若实际数据中离散特征数量少于8个,自动隐藏剩余子图)
for idx in range(len(discrete_features), len(axes)):
axes[idx].set_visible(False)
# ---------------------- 5. 调整子图间距,避免重叠----------------------
plt.tight_layout()
# 显示图表
plt.show()
# (可选)保存图表
# plt.savefig('离散特征条形图.png', dpi=300, bbox_inches='tight')
# ---------------------- 可视化配置(复用)----------------------
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
target_name = feature_name_mapping['target'] # 目标变量中文名称
# ---------------------- 1. 连续特征 × 标签:分组小提琴图(2行3列)----------------------
fig1, axes1 = plt.subplots(2, 3, figsize=(15, 10))
axes1 = axes1.flatten()
for idx, feat in enumerate(continuous_features):
# 按标签分组提取数据(0=未患病,1=患病,根据实际标签取值调整)
data_0 = data[data['target'] == 0][feat].dropna()
data_1 = data[data['target'] == 1][feat].dropna()
# 绘制分组小提琴图
parts = axes1[idx].violinplot([data_0, data_1], positions=[0, 1], showmeans=True, showmedians=True)
# 样式优化(不同标签用不同颜色)
colors = ['lightblue', 'lightcoral']
for i, pc in enumerate(parts['bodies']):
pc.set(facecolor=colors[i], edgecolor=['darkblue', 'darkred'][i], alpha=0.7)
parts['cmeans'].set(color='black', linewidth=2)
parts['cmedians'].set(color='gold', linewidth=2)
# 标签设置
axes1[idx].set_title(f'{feature_name_mapping[feat]} × {target_name}', fontsize=12, fontweight='bold')
axes1[idx].set_xlabel(target_name, fontsize=10)
axes1[idx].set_ylabel(feature_name_mapping[feat], fontsize=10)
axes1[idx].set_xticks([0, 1])
axes1[idx].set_xticklabels(['未患病(0)', '患病(1)']) # 按实际标签含义调整
axes1[idx].tick_params(labelsize=9)
# 隐藏多余子图
for idx in range(len(continuous_features), len(axes1)):
axes1[idx].set_visible(False)
plt.tight_layout(), plt.show()
# ---------------------- 2. 离散特征 × 标签:分组条形图(2行4列)----------------------
fig2, axes2 = plt.subplots(2, 4, figsize=(18, 10))
axes2 = axes2.flatten()
for idx, feat in enumerate(discrete_features):
# 按标签分组统计频次(交叉表)
cross_tab = pd.crosstab(data[feat], data['target'], normalize='index') * 100 # 按特征取值归一化(百分比)
# 绘制分组条形图
x = np.arange(len(cross_tab.index))
width = 0.35
bars1 = axes2[idx].bar(x - width/2, cross_tab[0], width, label='未患病(0)', color='lightblue', edgecolor='darkblue', alpha=0.8)
bars2 = axes2[idx].bar(x + width/2, cross_tab[1], width, label='患病(1)', color='lightcoral', edgecolor='darkred', alpha=0.8)
# 添加百分比标签
for bars in [bars1, bars2]:
for bar in bars:
height = bar.get_height()
axes2[idx].text(bar.get_x() + bar.get_width()/2, height + 1,
f'{height:.1f}%', ha='center', va='bottom', fontsize=8)
# 标签设置
axes2[idx].set_title(f'{feature_name_mapping[feat]} × {target_name}', fontsize=12, fontweight='bold')
axes2[idx].set_xlabel(f'{feature_name_mapping[feat]} 取值', fontsize=10)
axes2[idx].set_ylabel('占比(%)', fontsize=10)
axes2[idx].set_xticks(x)
axes2[idx].set_xticklabels(cross_tab.index.astype(str))
axes2[idx].legend(fontsize=9)
axes2[idx].set_ylim(0, 105) # 预留百分比标签空间
axes2[idx].tick_params(labelsize=9)
# 隐藏多余子图
for idx in range(len(discrete_features), len(axes2)):
axes2[idx].set_visible(False)
plt.tight_layout(), plt.show()
# ---------------------- 1. 计算特征相关性矩阵(仅用特征,排除目标变量)----------------------
# 合并连续+离散特征(排除target)
all_used_features = continuous_features + discrete_features
corr_matrix = data[all_used_features].corr() # 计算Pearson相关系数
# ---------------------- 2. 定义3种常用配色方案 ----------------------
cmap_list = [
'RdBu_r', # 红-蓝反向(经典对比色,正相关红、负相关蓝)
'YlOrRd', # 黄-橙-红(暖色调,适合突出正相关)
'coolwarm' # 冷-暖过渡(柔和对比,适合多特征场景)
]
# ---------------------- 3. 循环绘制3种配色热力图 ----------------------
for i, cmap in enumerate(cmap_list, 1):
plt.figure(figsize=(12, 10)) # 固定画布大小,保证清晰度
# 绘制热力图
im = plt.imshow(corr_matrix, cmap=cmap, aspect='auto', vmin=-1, vmax=1)
# 添加数值标注(保留2位小数,增强可读性)
for x in range(len(corr_matrix.index)):
for y in range(len(corr_matrix.columns)):
plt.text(y, x, f'{corr_matrix.iloc[x, y]:.2f}',
ha='center', va='center', fontsize=8,
color='white' if abs(corr_matrix.iloc[x, y]) > 0.5 else 'black') # 高相关用白字
# 标签与刻度设置(用中文特征名)
chinese_labels = [feature_name_mapping[feat] for feat in all_used_features]
plt.xticks(range(len(all_used_features)), chinese_labels, rotation=45, ha='right', fontsize=10)
plt.yticks(range(len(all_used_features)), chinese_labels, fontsize=10)
# 添加颜色条(标注相关系数范围)
cbar = plt.colorbar(im, shrink=0.8)
cbar.set_label('Pearson 相关系数', fontsize=12)
cbar.ax.tick_params(labelsize=9)
# 标题与布局
plt.title(f'特征相关性热力图(配色:{cmap})', fontsize=14, fontweight='bold', pad=20)
plt.tight_layout() # 自动调整布局,避免标签截断
# 保存图片(清晰度300dpi),可替换路径
plt.savefig(f'特征相关性热力图_{cmap}.png', dpi=300, bbox_inches='tight')
plt.close() # 关闭当前图,避免内存占用
print("3种配色热力图已保存(dpi=300),分别为:RdBu_r、YlOrRd、coolwarm")
图:
1.连续变量的箱线图

2.连续变量的小提琴图

3.离散变量的条形图

4.连续变量与标签的关系图(小提琴图)

5.离散变量与标签的关系图(条形图)

6.热力图



更多推荐
所有评论(0)