探索性数据分析(EDA)
探索性数据分析 (EDA)
概览
探索性数据分析(EDA)是数据科学项目中至关重要的第一步,系统地检查数据集以了解它们的特性,识别模式,并在正式建模前评估数据质量。
核心概念
- 数据剖析:理解基本统计和数据类型
- 分布分析:检查变量的分布情况
- 关系发现:识别变量之间的模式
- 异常值检测:寻找异常值和不寻常的模式
- 数据质量评估:评估完整性和一致性
使用场景
- 开始新的数据集分析
- 在建模前理解数据
- 识别数据质量问题
- 为测试生成假设
- 向利益相关者传达洞察
使用Python实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 加载和探索数据
df = pd.read_csv('customer_data.csv')
# 基本剖析
print(f"形状:{df.shape}")
print(f"数据类型:
{df.dtypes}")
print(f"缺失值:
{df.isnull().sum()}")
print(f"重复项:{df.duplicated().sum()}")
# 统计总结
print(df.describe())
print(df.describe(include='object'))
# 分布分析 - 数值列
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
df['age'].hist(bins=30, ax=axes[0, 0])
axes[0, 0].set_title('年龄分布')
df['income'].hist(bins=30, ax=axes[0, 1])
axes[0, 1].set_title('收入分布')
# 箱线图用于异常值检测
df.boxplot(column='age', by='region', ax=axes[1, 0])
axes[1, 0].set_title('按地区分的年龄')
# 分类分析
df['category'].value_counts().plot(kind='bar', ax=axes[1, 1])
axes[1, 1].set_title('类别分布')
plt.tight_layout()
plt.show()
# 相关性分析
numeric_df = df.select_dtypes(include=[np.number])
correlation_matrix = numeric_df.corr()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('相关性矩阵')
plt.show()
# 多变量关系
sns.pairplot(df[['age', 'income', 'education_years']], diag_kind='hist')
plt.show()
# 偏度和峰度
print("
偏度:")
print(numeric_df.skew())
print("
峰度:")
print(numeric_df.kurtosis())
# 百分位数分析
print("
年龄的百分位数:")
print(df['age'].quantile([0.25, 0.5, 0.75, 0.95, 0.99]))
# 缺失数据模式
missing_pct = (df.isnull().sum() / len(df) * 100)
missing_pct[missing_pct > 0].sort_values(ascending=False)
# 值计数分析
print("
客户类型分布:")
print(df['customer_type'].value_counts(normalize=True))
# 高级EDA:分组分析
print("
分组分析:")
print(df.groupby('region')[['age', 'income']].agg(['mean', 'median', 'std']))
# 与目标变量的相关性
if 'target' in df.columns:
target_corr = df.corr()['target'].sort_values(ascending=False)
print("
特征与目标的相关性:")
print(target_corr)
# 数据类型分解
print("
数据类型总结:")
print(df.dtypes.value_counts())
# 唯一值计数
print("
唯一值计数:")
print(df.nunique().sort_values(ascending=False))
# 方差分析
print("
每个特征的方差:")
numeric_cols = df.select_dtypes(include=[np.number]).columns
for col in numeric_cols:
variance = df[col].var()
print(f" {col}: {variance:.2f}")
# 分布模式
for col in df.select_dtypes(include=[np.number]).columns:
skew = df[col].skew()
kurt = df[col].kurtosis()
print(f"{col} - 偏度:{skew:.2f}, 峰度:{kurt:.2f}")
# 双变量分析
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
df.groupby('region')['income'].mean().plot(kind='bar', ax=axes[0])
axes[0].set_title('按地区分的平均收入')
df.groupby('category')['age'].mean().plot(kind='bar', ax=axes[1])
axes[1].set_title('按类别分的平均年龄')
plt.tight_layout()
plt.show()
# 综合数据剖析
print("
综合数据剖析:")
profile = {
'变量': df.columns,
'类型': df.dtypes,
'非空计数': df.count(),
'空计数': df.isnull().sum(),
'唯一值': df.nunique(),
}
profile_df = pd.DataFrame(profile)
print(profile_df)
高级EDA技术
# 步骤15:交互分析
import itertools
numeric_cols = df.select_dtypes(include=[np.number]).columns
interaction_strengths = []
for col1, col2 in itertools.combinations(numeric_cols[:5], 2):
interaction_score = abs(df[col1].corr(df[col2]))
interaction_strengths.append({
'对': f"{col1} × {col2}",
'相关性': interaction_score,
})
interaction_df = pd.DataFrame(interaction_strengths).sort_values('相关性', ascending=False)
print("
顶级交互:")
print(interaction_df.head())
# 步骤16:异常值总结
for col in numeric_cols:
Q1, Q3 = df[col].quantile([0.25, 0.75])
IQR = Q3 - Q1
outliers = df[(df[col] < Q1 - 1.5*IQR) | (df[col] > Q3 + 1.5*IQR)]
if len(outliers) > 0:
print(f"
{col}: 检测到{len(outliers)}个异常值({len(outliers)/len(df)*100:.1f}%)")
# 步骤17:生成自动化洞察
print("
" + "="*60)
print("自动化数据洞察")
print("="*60)
for col in numeric_cols:
skewness = df[col].skew()
mean_val = df[col].mean()
median_val = df[col].median()
if abs(skewness) > 1:
direction = "右" if skewness > 0 else "左"
print(f"{col}: 分布高度{direction}偏斜")
if abs(mean_val - median_val) > 0.1 * median_val:
print(f"{col}: 均值和中位数差异显著")
print("="*60)
需要问的关键问题
- 数据的维度和类型是什么?
- 关键变量的分布如何?
- 变量之间存在什么模式?
- 是否有明显的数据质量问题?
- 存在哪些异常值或异常?
- 我们可以生成哪些假设?
最佳实践
- 在可视化之前先进行数据剖析
- 提早检查数据类型和缺失值
- 在分析前先可视化分布
- 记录有趣的发现和异常
- 为利益相关者沟通创建摘要
- 使用领域知识解释模式
常见陷阱
- 跳过数据质量检查
- 在小数据集中过度解释模式
- 忽略领域背景
- 可视化数据不足
- 未系统记录发现
交付物
- 包含缺失值和重复项的数据质量报告
- 统计总结和分布图表
- 相关性和关系可视化
- 显著模式和异常列表
- 进一步调查的假设
- 数据清洗建议