当前位置: 首页 > news >正文

机器学习特征预处理之分类缺失填充

示例

import pandas as pd import numpy as np from sklearn.impute import SimpleImputer def categorical_imputation(X_train, X_test, cat_cols, strategy='most_frequent', fill_value=None, verbose=True): """ 分类缺失填充 - 必须在编码前执行! """ if not cat_cols: return X_train, X_test # ⭐ 关键修复:统一将 None 转换为 np.nan X_train = X_train.replace({None: np.nan}) X_test = X_test.replace({None: np.nan}) def is_categorical_column(col): if col not in X_train.columns: return False if (pd.api.types.is_object_dtype(X_train[col]) or pd.api.types.is_categorical_dtype(X_train[col]) or pd.api.types.is_string_dtype(X_train[col])): return True if pd.api.types.is_integer_dtype(X_train[col]): n_unique = X_train[col].nunique() n_total = len(X_train[col]) if n_total > 0 and n_unique / n_total < 0.05: if verbose: print(f" ℹ️ '{col}' 识别为整数编码分类 (唯一值: {n_unique})") return True return False valid_cat_cols = [col for col in cat_cols if is_categorical_column(col)] ignored_cols = set(cat_cols) - set(valid_cat_cols) if ignored_cols and verbose: print(f" ⚠️ 忽略以下列: {ignored_cols}") if not valid_cat_cols: if verbose: print(f" ⚠️ 没有有效的分类列需要填充") return X_train, X_test valid_strategies = ['most_frequent', 'constant'] if strategy not in valid_strategies: if verbose: print(f" ⚠️ 策略 '{strategy}' 不适用于分类数据,切换为 'most_frequent'") strategy = 'most_frequent' if strategy == 'constant' and fill_value is None: fill_value = 'UNKNOWN' if verbose: print(f" ℹ️ fill_value未指定,使用默认值: '{fill_value}'") for col in valid_cat_cols: train_vals = set(X_train[col].dropna().unique()) test_vals = set(X_test[col].dropna().unique()) new_cats = test_vals - train_vals if new_cats and verbose: print(f" ⚠️ 测试集新类别 '{col}': {new_cats}") try: if strategy == 'constant': imputer = SimpleImputer(strategy=strategy, fill_value=fill_value) else: imputer = SimpleImputer(strategy=strategy) X_train.loc[:, valid_cat_cols] = imputer.fit_transform(X_train[valid_cat_cols]) X_test.loc[:, valid_cat_cols] = imputer.transform(X_test[valid_cat_cols]) if verbose: print(f" ✅ 分类填充完成: {len(valid_cat_cols)} 列 (策略: {strategy})") except Exception as e: print(f" ❌ 分类填充失败: {e}") print(f" 问题列: {valid_cat_cols}") print(f" 数据类型: {X_train[valid_cat_cols].dtypes}") raise return X_train, X_test

调用示例

print("=" * 60) print("测试场景1:基本众数填充") print("=" * 60) # 创建训练集 X_train = pd.DataFrame({ 'color': ['red', 'blue', None, 'red', 'green', None], 'size': ['M', 'L', 'M', None, 'S', 'M'], 'category': ['A', 'B', 'A', 'C', None, 'A'], 'price': [100, 200, 150, 300, 250, 180] # 数值列 }) # 创建测试集 X_test = pd.DataFrame({ 'color': ['blue', None, 'red'], 'size': ['L', 'M', None], 'category': ['B', 'C', 'A'], 'price': [220, 190, 210] }) print("原始训练集:") print(X_train) print("\n原始测试集:") print(X_test) # 执行填充 cat_cols = ['color', 'size', 'category'] X_train_filled, X_test_filled = categorical_imputation( X_train, X_test, cat_cols, strategy='most_frequent' ) print("\n填充后的训练集:") print(X_train_filled) print("\n填充后的测试集:") print(X_test_filled) # 验证填充结果 print("\n验证填充结果:") for col in cat_cols: mode_val = X_train[col].mode()[0] print(f" {col}: 众数 = '{mode_val}'") print(f" 训练集缺失值: {X_train[col].isna().sum()} → 填充为 '{mode_val}'") print(f" 测试集缺失值: {X_test[col].isna().sum()} → 填充为 '{mode_val}'")

数据缺失填充策略

1. Mean(均值)

  • 操作:用该特征(列)的算术平均数来填充缺失值。

  • 适用场景:数据呈正态分布对称分布,且没有明显极端值时。

  • 优点:计算简单,能保持数据的整体均值不变。

  • 致命缺点极易受异常值影响。如果数据里有极端大或极端小的数,均值会被“拉偏”,填充出来的结果可能失真。

2. Median(中位数)

  • 操作:用该特征(列)的中位数(即按大小排序后位于中间的那个数)来填充缺失值。

  • 适用场景:数据分布明显偏斜(如收入数据,大部分人收入低,极少数人收入极高),或者存在异常值时。

  • 优点稳健性极强。因为只看位置,所以极端值的大小对中位数毫无影响,比均值更“抗造”。

3. Most_frequent(众数)

  • 操作:用该特征(列)中出现频率最高的那个值来填充缺失值。

  • 适用场景:专门用于分类(离散型)数据,比如性别(男/女)、颜色(红/蓝/绿)。

  • 注意:如果缺失值很多,或者众数占比不高,填充后可能会过度强化该类别,导致数据多样性降低。在连续型数据中基本不用这个方法。

4. Constant(常量)

  • 操作:用一个自定义的固定值(通常是“0”、“未知”、“-999”或“None”)来填充所有缺失值。

  • 适用场景

    • 业务上缺失就是有特殊含义的(比如“该用户未消费”,金额填0);

    • 作为机器学习中的占位符,告诉算法“这个值是人为补的,不代表真实水平”。

  • 缺点:如果随意填一个毫无意义的常数(比如用0填年龄),会严重干扰数据分析,必须谨慎使用。


简单粗暴的速记口诀

  • 数据像钟形曲线(对称)→ 用Mean

  • 数据有暴发户(极端值)→ 用Median

  • 数据是类别标签(男女/颜色)→ 用Most_frequent

  • 数据缺失本身就是信息(填无/填0)→ 用Constant

http://www.jsqmd.com/news/1196170/

相关文章:

  • 7.15 答辩稿
  • 新手做抖音小店无货源,商品卡自然流怎么选品?工具直接套用 - 电商分享
  • 如何用 5 种终极方法将 Redmi 手机恢复出厂设置
  • 2026福州外墙渗漏、卫生间漏水、楼顶、地下室、阳台+阳光房渗漏别踩坑!3家正规服务商(7月) - 防水企业百科
  • 编程启蒙|Scratch 转 Python 系列第8天:节奏敲击机游戏实战(AI节奏谱生成实战)
  • 边缘推理多实例并发服务架构设计:模型共享内存池与请求级 Arena 隔离方案的工程实现
  • CSS弹性盒子布局(Flexbox)详解
  • 双二阶IIR滤波器——定点数实现与结构选择考量
  • arm smmu学习备忘
  • 【网络协议实战】——双协议栈(Dual Stack)部署与配置指南
  • Android随笔-Context
  • 独立站没询盘、谷歌SEO难做?2026外贸真正的免费出海流量在AI - GrowthUME
  • 多模态模型推理的算子调度优化:视觉 Encoder 与语言 Decoder 的流水线并行策略
  • 从数据库到 Fiori 页面,Field Extensibility 如何让自定义字段贯穿整条应用链路
  • 巴西全年重点行业展会汇总
  • 美度中国官方售后服务中心|服务热线及全部官方地址权威信息声明(2026年7月更新) - 亨得利官方服务中心
  • ChatGPT谈薪成功率提升4.2倍的关键:不是问“我能涨多少”,而是用这6个结构化追问
  • 协作机器人的有效负载与速度曲线:如何平衡性能与效率
  • 【AI术语】
  • 2026株洲黄金回收权威评测:全资质+全城覆盖,湘奢汇(天元店)登顶S级推荐 - 生活测评小能手
  • 从零构建图查询:Cypher 核心语法实战指南
  • VC++底层解析WAV文件:从RIFF格式到采样率读取实战
  • FreeCAD基本教程-放样操作-天圆地方
  • C++、Go、Rust混合架构实战:构建高性能产业政策分析平台
  • 2026武汉卫生间漏水、外墙、楼顶、地下室、阳光房渗漏怎么选?3家口碑服务商盘点(7月) - 防水企业百科
  • 从555定时器到数码管:揭秘简易数字电容测量仪的设计与实现
  • RFID固定资产管理系统:技术原理与部署实
  • 线性算子不是空间映射函数,是全域双螺旋场之间拉伸、旋转、耦合、坍缩的跨空间标准化变换载体《全域数学vs传统数学:人类文明进阶200讲》第80讲
  • 揭秘AI记忆系统:短期与长期记忆如何协同工作
  • 基于 ESP32 的图书馆静音舱环境自适应与占用状态感知系统设计与实现