聚类分析如何处理空值?fintech场景下K-Means保留NaN无交互信息方法
问题解决思路
scikit-learn原生K-Means不支持直接处理NaN值,你可以通过特征工程改造输入数据的方式,完整保留「无交互」的属性信息,不需要删除样本也不需要用均值/中位数填充。
具体实现步骤
1. 特征拆分编码
对每个原始日度交易字段(day1~day4),拆分为2个独立特征,完整还原原始信息:
- 交互标识特征:命名为
{原字段名}_has_interaction,取值为1代表当日有交易(原始值非NaN),取值为0代表当日无交互(原始值为NaN),单独保留你需要的无交互类别属性 - 借贷净额特征:命名为
{原字段名}_net_amount,原始值非NaN的保留原值,NaN统一填充为0即可。因为已经通过交互标识字段区分了无交互场景,这里的0不会和原始「当日借贷金额相等」的0混淆,两个特征组合就能完全区分两种场景
举个例子:原始day1值为NaN的用户,拆完后
day1_has_interaction=0、day1_net_amount=0;原始day1值为0的用户,拆完后day1_has_interaction=1、day1_net_amount=0,二者特征完全不同,K-Means计算距离时会自然区分开。
2. 可选特征标准化
如果不同日期的借贷净额数值范围差异较大,建议对所有净额特征做标准化处理,避免量纲影响聚类效果,0/1格式的交互标识特征不需要标准化。
3. 执行K-Means聚类
将拼接后的所有新特征作为输入,直接调用sklearn原生KMeans接口即可正常运行。
代码示例
import pandas as pd from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler # 假设df为你的原始数据集,包含customer_id和day1~day4字段 raw_date_cols = ["day1", "day2", "day3", "day4"] processed_feature_list = [] # 逐字段拆分特征 for col in raw_date_cols: # 生成当日是否有交互的标识列 df[f"{col}_has_interaction"] = df[col].notna().astype(int) processed_feature_list.append(f"{col}_has_interaction") # 生成净额列,无交互场景填充0 df[f"{col}_net_amount"] = df[col].fillna(0) processed_feature_list.append(f"{col}_net_amount") # 对净额字段做标准化(可选) scaler = StandardScaler() amount_cols = [col for col in processed_feature_list if "net_amount" in col] df[amount_cols] = scaler.fit_transform(df[amount_cols]) # 执行K-Means聚类 kmeans_model = KMeans(n_clusters=3, random_state=42) df["cluster_label"] = kmeans_model.fit_predict(df[processed_feature_list])
方案优势
- 完全保留了NaN代表的「无交互」信息,不会和原始的0值场景混淆
- 不需要修改K-Means底层实现,完全适配sklearn原生API
- 特征解释性强,后续聚类结果分析时可以直接定位不同客群的交易频次、借贷净额特征差异
内容的提问来源于stack exchange,提问作者Musaib Jan
相关产品推荐
相关产品推荐

