如何在PySpark中按比例填充DataFrame列的缺失值?
按比例填充DataFrame缺失值的可复用实现方案
基于你现有Counter列的实现
你已经通过row_number()生成了Counter列,接下来可以通过参数化比例的方式实现可复用的填充逻辑:
步骤1:计算填充数量
先统计Type列的缺失值总数,再根据设定的比例计算需要填充"R"和"NR"的数量:
from pyspark.sql import functions as F from pyspark.sql.window import Window # 统计Type列缺失值总数 total_missing = Df.filter(F.col("Type").isNull()).count() # 定义比例参数(可根据需求修改) r_ratio = 0.8 r_count = int(total_missing * r_ratio) nr_count = total_missing - r_count
步骤2:基于Counter列填充缺失值
用when条件判断Counter的范围,完成填充:
Df_filled = Df.withColumn( "Type", # 仅对缺失值进行填充,非缺失值保留原内容 F.when(F.col("Type").isNull(), F.when(F.col("Counter") <= r_count, "R").otherwise("NR") ).otherwise(F.col("Type")) )
更通用的可复用函数(无需Counter列)
如果不需要固定填充位置,推荐用随机分配的方式实现,适配任意比例且更灵活:
from pyspark.sql import functions as F from pyspark.sql.window import Window def fill_type_by_ratio(df, r_ratio=0.8, seed=None): """ 按比例填充DataFrame中Type列的缺失值 :param df: 输入DataFrame :param r_ratio: "R"的填充比例(默认0.8) :param seed: 随机种子(可选,用于固定随机结果) :return: 填充后的DataFrame """ # 分离缺失行和非缺失行 missing_df = df.filter(F.col("Type").isNull()) non_missing_df = df.filter(F.col("Type").isNotNull()) total_missing = missing_df.count() if total_missing == 0: return df # 计算各值的填充数量 r_count = int(total_missing * r_ratio) # 添加随机数,用于随机分配填充值 rand_col = F.rand(seed=seed) if seed else F.rand() missing_df = missing_df.withColumn("rand_num", rand_col) # 按随机数排序后分配R/NR filled_missing = missing_df.withColumn( "Type", F.when(F.row_number().over(Window.orderBy("rand_num")) <= r_count, "R").otherwise("NR") ).drop("rand_num") # 合并结果 return non_missing_df.union(filled_missing) # 使用示例 # 80%R、20%NR填充 Df_filled_8020 = fill_type_by_ratio(Df, r_ratio=0.8) # 70%R、30%NR填充 Df_filled_7030 = fill_type_by_ratio(Df, r_ratio=0.7) # 固定随机结果(设置种子) Df_fixed = fill_type_by_ratio(Df, r_ratio=0.8, seed=42)
该函数的优势
- 高度可复用:只需传入DataFrame和目标比例,即可适配任意R/NR的填充比例
- 随机公平:通过随机数分配填充值,避免固定位置填充的局限性
- 鲁棒性强:自动处理无缺失值的情况,直接返回原DataFrame
注意事项
- 当缺失值总数×比例不是整数时,
int()会向下取整,若需要四舍五入可替换为round() - 若需要固定填充结果,可在随机函数中设置种子参数
内容的提问来源于stack exchange,提问作者Marco Pasqua
相关产品推荐
相关产品推荐

