PySpark实现动态交叉验证目标均值编码(CV-Target-Mean-Encode)
我来帮你解决这个PySpark下动态生成交叉验证目标均值编码的问题,这在特征工程里很常见,尤其是CV-Target-Mean-Encode场景。下面是适配Python3.6和Spark2.3的完整方案:
环境与原始数据
使用环境:Python 3.6、Spark 2.3
原始DataFrame示例:
key a_fold_0 b_fold_0 a_fold_1 b_fold_1 a_fold_2 b_fold_2 1 1 2 3 4 5 6 2 7 5 3 5 2 1
需求规则
需要为每个特征前缀(比如a、b)和每个fold编号(比如0、1、2)生成对应的均值列,规则为:
- fold_0的均值 = (fold_1列值 + fold_2列值)/2
- fold_1的均值 = (fold_0列值 + fold_2列值)/2
- fold_2的均值 = (fold_0列值 + fold_1列值)/2
核心要求:列数、fold数量均为动态值,代码需自动适配。
实现方案
步骤1:解析fold列的元信息
首先通过正则表达式从列名中提取特征前缀和fold编号,这是动态处理的基础:
import re from pyspark.sql import functions as F # 假设你的原始DataFrame名为df fold_cols = [col for col in df.columns if re.match(r'.*_fold_\d+', col)] # 提取所有特征前缀和fold编号 prefixes = set() fold_nums = set() for col in fold_cols: match_result = re.match(r'(\w+)_fold_(\d+)', col) if match_result: prefixes.add(match_result.group(1)) fold_nums.add(int(match_result.group(2))) # 对fold编号排序,保证计算逻辑有序 fold_nums = sorted(fold_nums) total_folds = len(fold_nums)
步骤2:动态生成均值列计算表达式
遍历每个特征前缀和fold编号,根据规则生成对应的均值列表达式,这里会自动适配任意数量的fold:
# 先保留所有原始列 select_exprs = [F.col(col) for col in df.columns] for prefix in prefixes: for target_fold in fold_nums: # 筛选出当前fold之外的所有其他fold other_folds = [f for f in fold_nums if f != target_fold] # 计算其他fold列的总和,再除以数量得到均值 sum_other = sum([F.col(f"{prefix}_fold_{f}") for f in other_folds]) mean_col = (sum_other / len(other_folds)).alias(f"{prefix}_fold_{target_fold}_mean") select_exprs.append(mean_col) # 生成最终的结果DataFrame result_df = df.select(select_exprs)
步骤3:验证结果
运行代码后,result_df会包含所有原始列和新增的均值列。比如对于示例数据中的key=1:
a_fold_0_mean= (3 + 5)/2 = 4b_fold_0_mean= (4 + 6)/2 = 5a_fold_1_mean= (1 + 5)/2 = 3
完全符合你给出的示例规则。
关键优势
- 动态适配:不管fold数量是3个还是更多(比如4个fold时,均值会自动取另外3个fold的平均),代码都能正常运行
- 性能高效:使用PySpark内置函数完成计算,避免自定义UDF,保证大数据量下的处理效率
- 扩展性强:只要列名符合
{特征前缀}_fold_{编号}的格式,就能自动解析处理
内容的提问来源于stack exchange,提问作者Aakash Basu
相关产品推荐
相关产品推荐

