python day7
·
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
data.info() # 列名、非空值、数据类型
data.columns # 所有列名 data的属性
data.dtypes
data.isnull() # 布尔矩阵显示缺失值,这个方法返回一个布尔矩阵,也是dataframe对象,其中True表示是缺失值,False表示不是缺失值。
data.isnull().sum()
# 无缺失值,所以不用补值
# 找到所有的连续特征
continuous_features = data.select_dtypes(include=['float64', 'int64']).columns.tolist()
continuous_features
discrete_features = [feat for feat in data.columns.tolist() if feat not in continuous_features]
discrete_features
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"] # 支持常见中文字体
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示异常
# 屏蔽 matplotlib 关于字体查找的警告日志
logging.getLogger('matplotlib.font_manager').setLevel(logging.ERROR)
# 后续正常执行可视化代码即可
# (例如之前的 age 特征可视化代码)
data['age']
import matplotlib.pyplot as plt
import logging
# -------------------------- 前提:假设已加载数据(此处用模拟数据示例,可替换为真实数据) --------------------------
# 若使用真实数据,直接替换为 df = pd.read_csv("你的数据文件.csv") 等加载方式
np.random.seed(42) # 固定随机种子,保证结果可复现
age_data = np.random.normal(loc=35, scale=12, size=1000) # 模拟age数据:均值35,标准差12,1000个样本
age_data = np.clip(age_data, a_min=0, a_max=100) # 限制age范围在0-100(符合实际年龄逻辑)
df = pd.DataFrame({"age": age_data}) # 转换为DataFrame,便于后续可视化调用
# -------------------------- 1. 箱线图(Box Plot):展示分布四分位数、异常值 --------------------------
plt.figure(figsize=(8, 5)) # 设置画布大小
sns.boxplot(x="age", data=df, palette="Set2", linewidth=1.5, flierprops={"marker": "o", "markerfacecolor": "red", "markersize": 5})
plt.title("Age特征箱线图", fontsize=14, fontweight="bold", pad=20) # 标题:加粗、调整间距
plt.xlabel("年龄(岁)", fontsize=12) # x轴标签
plt.xticks(fontsize=10) # x轴刻度字体大小
plt.grid(axis="x", alpha=0.3, linestyle="--") # 添加x轴网格线(浅灰色虚线,增加可读性)
plt.tight_layout() # 自动调整布局,避免标签被截断
plt.show() # 显示图像
# -------------------------- 2. 小提琴图(Violin Plot):结合箱线图与密度分布 --------------------------
plt.figure(figsize=(8, 5))
sns.violinplot(x="age", data=df, palette="Set2", inner="quartile", linewidth=1.5) # inner="quartile"显示四分位数
plt.title("Age特征小提琴图", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("年龄(岁)", fontsize=12)
plt.xticks(fontsize=10)
plt.grid(axis="x", alpha=0.3, linestyle="--")
plt.tight_layout()
plt.show()
# -------------------------- 3. 直方图(Histogram):展示样本频次分布 --------------------------
plt.figure(figsize=(10, 6))
# 手动设置bins(区间数),避免自动分箱不合理;edgecolor="black"增加柱子边框,区分相邻柱子
n, bins, patches = plt.hist(df["age"], bins=20, edgecolor="black", alpha=0.7, color="#66b3ff")
# 为直方图添加“频次标签”(可选,增强信息传递)
for i in range(len(patches)):
height = patches[i].get_height()
if height > 0: # 只对有数据的柱子添加标签
plt.text(patches[i].get_x() + patches[i].get_width()/2., height + 1,
f"{int(height)}", ha="center", va="bottom", fontsize=9)
plt.title("Age特征直方图", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("年龄(岁)", fontsize=12)
plt.ylabel("样本频次", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.grid(axis="y", alpha=0.3, linestyle="--") # y轴网格线,辅助读取频次
plt.tight_layout()
plt.show()
# -------------------------- 4. 密度图(Density Plot):展示概率密度分布 --------------------------
plt.figure(figsize=(10, 6))
# 方法1:用seaborn的kdeplot(默认带阴影,更美观)
sns.kdeplot(df["age"], fill=True, color="#ff9999", alpha=0.6, linewidth=2, label="Age密度曲线")
# 方法2:用matplotlib的gaussian_kde(偏底层,可自定义程度更高,二选一即可)
# kde = stats.gaussian_kde(df["age"])
# x_range = np.linspace(df["age"].min() - 5, df["age"].max() + 5, 200) # 扩展x轴范围,使曲线更完整
# plt.plot(x_range, kde(x_range), color="#ff9999", linewidth=2, label="Age密度曲线")
# plt.fill_between(x_range, kde(x_range), alpha=0.6, color="#ff9999")
plt.title("Age特征密度图", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("年龄(岁)", fontsize=12)
plt.ylabel("概率密度", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.legend(fontsize=11) # 显示图例
plt.grid(axis="y", alpha=0.3, linestyle="--")
plt.tight_layout()
plt.show()
# -------------------------- 5. CDF图(累积分布函数图):展示“小于等于某值的样本占比” --------------------------
plt.figure(figsize=(10, 6))
# 步骤1:计算CDF的核心数据(排序后的age + 对应的累积概率)
sorted_age = np.sort(df["age"]) # 对age从小到大排序
cumulative_prob = np.arange(1, len(sorted_age) + 1) / len(sorted_age) # 累积概率(范围0-1)
# 步骤2:绘制CDF曲线(阶梯式,更符合离散样本的累积逻辑)
plt.step(sorted_age, cumulative_prob, where="post", color="#99ff99", linewidth=2, label="Age累积分布")
# 可选:添加“关键分位数标注”(如25%、50%、75%分位数)
percentiles = [25, 50, 75]
for p in percentiles:
p_val = np.percentile(df["age"], p) # 计算对应分位数的age值
p_prob = p / 100 # 对应累积概率
plt.scatter(p_val, p_prob, color="red", s=50, zorder=5) # 红色圆点标记分位数
plt.annotate(f"{p}%分位数: {p_val:.1f}岁",
xy=(p_val, p_prob), xytext=(10, 10),
textcoords="offset points", fontsize=10,
bbox=dict(boxstyle="round,pad=0.3", facecolor="yellow", alpha=0.7)) # 标注框
plt.title("Age特征CDF图(累积分布函数)", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("年龄(岁)", fontsize=12)
plt.ylabel("累积概率(≤当前年龄的样本占比)", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(np.arange(0, 1.1, 0.1), [f"{int(x*100)}%" for x in np.arange(0, 1.1, 0.1)], fontsize=10) # y轴用百分比显示
plt.grid(alpha=0.3, linestyle="--")
plt.legend(fontsize=11)
plt.tight_layout()
plt.show()
# -------------------------- 前提:假设已加载数据(此处用模拟数据示例,可替换为真实数据) --------------------------
# 真实数据直接替换为:df = pd.read_csv("你的数据文件.csv")(需包含"age"列和"target"列)
np.random.seed(42)
# 模拟二分类target(0/1),也可改为多分类(如0/1/2),代码兼容
df = pd.DataFrame({
"age": np.clip(np.random.normal(loc=35, scale=12, size=1000), 0, 100), # age范围0-100
"target": np.random.randint(0, 2, size=1000) # 二分类标签(0/1),多分类可改为0,3
})
# 若target是字符串标签(如"正常"/"异常"),无需修改代码,自动兼容
# -------------------------- 1. 按target分组的箱线图:对比不同类别age的分布统计量 --------------------------
plt.figure(figsize=(10, 6))
# x=target(分组依据),y=age(待展示特征),hue=target(颜色区分类别,更直观)
sns.boxplot(x="target", y="age", hue="target", data=df, palette="Set2",
linewidth=1.5, flierprops={"marker": "o", "markerfacecolor": "red", "markersize": 4},
dodge=False) # dodge=False避免分组重叠
plt.title("不同Target类别下Age的箱线图", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("Target标签", fontsize=12)
plt.ylabel("年龄(岁)", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.legend(title="Target类别", fontsize=10, title_fontsize=11)
plt.grid(axis="y", alpha=0.3, linestyle="--")
plt.tight_layout()
plt.show()
# -------------------------- 2. 按target分组的小提琴图:对比分布形状+统计量 --------------------------
plt.figure(figsize=(10, 6))
# inner="quartile"显示四分位数,与箱线图核心信息一致,同时展示密度分布
sns.violinplot(x="target", y="age", hue="target", data=df, palette="Set2",
inner="quartile", linewidth=1.5, dodge=False)
plt.title("不同Target类别下Age的小提琴图", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("Target标签", fontsize=12)
plt.ylabel("年龄(岁)", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.legend(title="Target类别", fontsize=10, title_fontsize=11)
plt.grid(axis="y", alpha=0.3, linestyle="--")
plt.tight_layout()
plt.show()
# -------------------------- 3. 按target分组的直方图:对比不同类别age的频次分布 --------------------------
plt.figure(figsize=(12, 6))
# 方法1:用seaborn的histplot(自动分组,支持stack/side-by-side)
sns.histplot(data=df, x="age", hue="target", multiple="dodge", # multiple="dodge"并列显示,"stack"堆叠显示
bins=20, edgecolor="black", alpha=0.7, palette="Set2")
# 方法2:用matplotlib手动分组(适合更精细控制)
# for target_val, color in zip(df["target"].unique(), ["#66b3ff", "#ff9999"]):
# age_subset = df[df["target"] == target_val]["age"]
# plt.hist(age_subset, bins=20, alpha=0.7, color=color, label=f"Target={target_val}",
# edgecolor="black")
plt.title("不同Target类别下Age的直方图", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("年龄(岁)", fontsize=12)
plt.ylabel("样本频次", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.legend(title="Target类别", fontsize=10, title_fontsize=11)
plt.grid(axis="y", alpha=0.3, linestyle="--")
plt.tight_layout()
plt.show()
# -------------------------- 4. 按target分组的密度图:对比不同类别age的概率密度 --------------------------
plt.figure(figsize=(12, 6))
# 用seaborn的kdeplot,按target自动分组,fill=True填充面积更易区分
sns.kdeplot(data=df, x="age", hue="target", fill=True, alpha=0.6,
linewidth=2, palette="Set2", common_norm=False) # common_norm=False:各曲线单独归一化(默认True)
# common_norm=True:所有曲线下面积总和=1;False:每条曲线下面积=1,更易对比形状
plt.title("不同Target类别下Age的密度图", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("年龄(岁)", fontsize=12)
plt.ylabel("概率密度", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(fontsize=10)
plt.legend(title="Target类别", fontsize=10, title_fontsize=11)
plt.grid(axis="y", alpha=0.3, linestyle="--")
plt.tight_layout()
plt.show()
# -------------------------- 5. 按target分组的CDF图:对比不同类别age的累积分布 --------------------------
plt.figure(figsize=(12, 6))
# 遍历每个target类别,单独计算并绘制CDF
for target_val, color, linestyle in zip(df["target"].unique(), ["#66b3ff", "#ff9999"], ["-", "--"]):
# 筛选当前target类别的age数据
age_subset = df[df["target"] == target_val]["age"]
# 计算CDF核心数据
sorted_age = np.sort(age_subset)
cumulative_prob = np.arange(1, len(sorted_age) + 1) / len(sorted_age) # 累积概率(0-1)
# 绘制CDF曲线(阶梯式)
plt.step(sorted_age, cumulative_prob, where="post", color=color,
linewidth=2, linestyle=linestyle, label=f"Target={target_val}")
# 可选:添加关键分位数标注(以50%分位数为例)
for target_val, color in zip(df["target"].unique(), ["#66b3ff", "#ff9999"]):
age_subset = df[df["target"] == target_val]["age"]
median = np.percentile(age_subset, 50)
plt.scatter(median, 0.5, color=color, s=60, zorder=5)
plt.annotate(f"Target={target_val} 中位数: {median:.1f}岁",
xy=(median, 0.5), xytext=(10, 10), textcoords="offset points",
fontsize=10, bbox=dict(boxstyle="round,pad=0.3", facecolor="yellow", alpha=0.7))
plt.title("不同Target类别下Age的CDF图(累积分布函数)", fontsize=14, fontweight="bold", pad=20)
plt.xlabel("年龄(岁)", fontsize=12)
plt.ylabel("累积概率(≤当前年龄的样本占比)", fontsize=12)
plt.xticks(fontsize=10)
plt.yticks(np.arange(0, 1.1, 0.1), [f"{int(x*100)}%" for x in np.arange(0, 1.1, 0.1)], fontsize=10)
plt.legend(title="Target类别", fontsize=10, title_fontsize=11)
plt.grid(alpha=0.3, linestyle="--")
plt.tight_layout()
plt.show()
更多推荐
所有评论(0)