4. 缺失值检测与处理:识别样本中的缺失值模式

知识图谱构建过程中,样本缺失值是最常见的数据质量问题之一。缺失值不仅会降低模型训练的有效性,还会在实体对齐、关系抽取等下游任务中引入系统性偏差。本章聚焦于如何系统性地检测样本中的缺失值模式,并通过可视化手段辅助决策,最终选择合理的填充或删除策略。

4.1 缺失值模式分类

在知识图谱样本中,缺失值并非随机出现,通常呈现三种结构模式。理解这些模式是选择处理策略的前提。

缺失模式 定义 知识图谱场景示例 处理倾向
完全随机缺失 (MCAR) 缺失与任何观测数据无关 传感器随机故障导致的关系属性缺失 可直接删除或简单填充
随机缺失 (MAR) 缺失依赖于其他观测变量 长尾实体更易缺失“别名”属性 需借助其他特征建模填充
非随机缺失 (MNAR) 缺失依赖于缺失值本身 高收入实体故意隐藏“收入”属性 需领域知识或敏感处理
校验提示: 在知识图谱样本中,MNAR 模式最容易引入样本偏差。例如,如果缺失“出生日期”的实体集中在某个地域,后续基于年龄的统计分析将产生系统性偏移。务必在检测阶段标记此类模式。

4.2 使用 isnull() 进行缺失值检测

Pandas 的 isnull() 方法是缺失值检测的起点。它返回一个布尔型 DataFrame,标识每个单元格是否为缺失值。结合 sum() 和 mean() 可以快速获取缺失概览。

import pandas as pd
import numpy as np

# 模拟知识图谱样本数据
kg_sample = pd.DataFrame({
    'entity_id': ['E001', 'E002', 'E003', 'E004', 'E005'],
    'type': ['Person', 'Organization', 'Person', 'Person', 'Organization'],
    'name': ['Alice', 'Acme Corp', np.nan, 'Bob', 'Beta Inc'],
    'birth_year': [1990, np.nan, 1985, np.nan, np.nan],
    'revenue': [np.nan, 5000000, np.nan, np.nan, 3000000],
    'country': ['US', 'US', 'CN', np.nan, 'CN']
})

# 缺失值数量统计
print(kg_sample.isnull().sum())

# 缺失值比例统计
print(kg_sample.isnull().mean().round(3) * 100)

输出示例:

entity_id      0
type           0
name           1
birth_year     3
revenue        3
country        1
dtype: int64

entity_id      0.0
type           0.0
name          20.0
birth_year    60.0
revenue       60.0
country       20.0
dtype: float64
关键指标: 当某列缺失比例超过 50% 时,需谨慎评估该属性在知识图谱中的保留价值。上例中 birth_year 和 revenue 缺失率达 60%,应考虑是否从图谱模式中移除或使用外部知识库补全。

4.3 使用热力图可视化缺失模式

单纯的数据表格难以直观呈现缺失值的分布规律。使用 Seaborn 的 heatmap 结合 isnull() 可以生成缺失值热力图,快速识别缺失的聚集区域和行间模式。

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(10, 6))
sns.heatmap(kg_sample.isnull(), cbar=False, cmap='viridis', yticklabels=False)
plt.title('知识图谱样本缺失值热力图', fontsize=14)
plt.xlabel('属性列')
plt.ylabel('样本行')
plt.tight_layout()
plt.show()

热力图中黄色表示存在值,紫色表示缺失值。通过观察紫色块的分布,可以判断缺失是随机散布还是集中在特定行或列。

缺失值模式检测与处理决策流程 原始知识图谱样本 步骤1: isnull() 布尔检测 + sum() 统计 步骤2: heatmap 可视化缺失模式 缺失率 < 5%: 直接删除 缺失率 5%-50%: 填充策略 缺失率 > 50%: 移除属性 决策需结合缺失模式(MCAR/MAR/MNAR)及知识图谱业务语义综合判断

4.4 缺失值处理策略:填充与删除

根据检测结果和缺失模式,选择以下策略之一进行处理。每种策略都有其适用场景和潜在风险。

4.4.1 删除策略

  • 行删除(listwise deletion): 直接删除包含缺失值的整行样本。适用于 MCAR 模式且缺失比例较低(<5%)的场景。
  • 列删除: 当某属性缺失比例过高(>50%)且无法通过外部知识补全时,从图谱模式中移除该属性。
  • 成对删除(pairwise deletion): 仅在计算特定属性对时排除缺失值,保留其他可用数据。适用于相关性分析阶段。
偏差风险警告: 在知识图谱中,如果缺失值集中在某个特定实体类型或关系方向上,直接行删除会导致该类型样本系统性减少,破坏图谱的覆盖均衡性。务必在删除前按实体类型分层统计缺失率。

4.4.2 填充策略

填充方法 适用数据类型 知识图谱场景示例 注意事项
固定值填充 类别型 / 数值型 缺失“国家”填充为“Unknown” 可能引入“未知”类别的聚集偏差
均值/中位数填充 数值型 缺失“收入”填充为同类实体中位数 降低方差,削弱极端值影响
众数填充 类别型 缺失“类型”填充为最频繁出现的类型 强化头部类别,削弱尾部类别
前向/后向填充 时序型 缺失“时间戳”使用相邻实体记录填充 仅适用于有序数据
模型预测填充 任意型 使用 KNN 或回归模型基于其他属性预测缺失值 计算成本高,可能过拟合
# 填充策略代码示例
from sklearn.impute import SimpleImputer

# 数值列:使用中位数填充
num_imputer = SimpleImputer(strategy='median')
kg_sample[['birth_year', 'revenue']] = num_imputer.fit_transform(kg_sample[['birth_year', 'revenue']])

# 类别列:使用众数填充
cat_imputer = SimpleImputer(strategy='most_frequent')
kg_sample[['name', 'country']] = cat_imputer.fit_transform(kg_sample[['name', 'country']])

print("填充后数据:")
print(kg_sample)
知识图谱缺失值填充策略选择矩阵 固定值填充 类别型缺失 引入“未知”类别 简单快速 统计量填充 均值/中位数/众数 数值型首选 降低方差 时序填充 前向/后向填充 时序数据专用 保持序列连续性 模型预测填充 KNN / 回归 高精度但高成本 需避免过拟合 选择条件优先级 1. 缺失率 < 5% → 直接删除行(最简单) 2. 缺失率 5%-20% → 固定值或统计量填充(平衡效率与效果) 3. 缺失率 20%-50% → 模型预测填充(需评估过拟合风险) 4. 缺失率 > 50% → 考虑移除该属性或使用外部知识库补全

4.5 填充后的偏差校验

填充操作本身可能引入新的偏差。完成填充后,必须进行以下校验:

  • 分布对比: 比较填充前后各属性的均值、方差、分位数分布,确保填充未显著改变原始分布形态。
  • 类别比例校验: 对于类别型属性,检查填充后各类别占比是否与原始非缺失数据一致。
  • 实体类型分层校验: 按实体类型(Person / Organization)分层统计填充量,避免某一类型被过度填充。
# 填充前后分布对比校验
print("填充前 birth_year 统计:")
print(kg_sample['birth_year'].describe())

print("\n填充后 birth_year 统计:")
print(kg_sample['birth_year'].describe())

# 类别比例校验
print("\n填充后 country 分布:")
print(kg_sample['country'].value_counts(normalize=True))
最佳实践: 在知识图谱项目中,建议保留原始缺失标记列(如 birth_year_missing 布尔列),以便在后续分析中追溯填充操作的影响。同时,将填充策略作为元数据记录在图谱的 provenance 层中。