基于PySpark GroupBy推导gender新列的技术方案问询
PySpark实现按Person分组推导Gender列
实现方案
通过头衔分类映射、分组聚合、规则匹配三个核心步骤完成需求,具体实现如下:
步骤1:初始化环境与数据
from pyspark.sql import SparkSession from pyspark.sql.functions import collect_set, when, col # 初始化SparkSession spark = SparkSession.builder.appName("GenderDerivation").getOrCreate() # 定义头衔分类集合 MALE_TITLES = {"Mr", "Lord"} FEMALE_TITLES = {"Ms", "Mrs", "Lady"} NEUTRAL_TITLES = {"Professor", "Prof", "Dr"} # 加载示例数据(可替换为实际数据源) data = [ ("SYNTHE02", "Mr"), ("SYNTHE02", "Dr"), ("SYNTHE03", "Mr"), ("SYNTHE03", "Mr"), ("SYNTHE05", "Mrs"), ("SYNTHE05", "Ms"), ("SYNTHE05", "Ms"), ("SYNTHE01", "Mrs"), ("SYNTHE01", "Dr"), ("SYNTHE01", "Ms"), ("SYNTHE07", "Dr"), ("SYNTHE07", "Prof"), ("SYNTHE08", "Mrs"), ("SYNTHE08", "Prof"), ("SYNTHE08", "Mr") ] df = spark.createDataFrame(data, ["person", "title"])
步骤2:映射头衔到性别分类
使用Spark内置函数完成分类映射,性能优于自定义UDF:
df_with_category = df.withColumn( "title_category", when(col("title").isin(MALE_TITLES), "MALE") .when(col("title").isin(FEMALE_TITLES), "FEMALE") .when(col("title").isin(NEUTRAL_TITLES), "NEUTRAL") .otherwise(None) # 处理未定义的头衔 )
步骤3:分组推导Gender
按person分组后,基于去重的分类集合匹配规则推导gender:
# 分组获取每个person的唯一头衔分类集合 grouped_df = df_with_category.groupBy("person") \ .agg(collect_set("title_category").alias("category_set")) # 按规则匹配gender(注意规则优先级) person_gender_df = grouped_df.withColumn( "gender", # 规则4:同时包含FEMALE和MALE when(col("category_set").contains("MALE") & col("category_set").contains("FEMALE"), "Unknown") # 规则1、5:包含MALE(无论是否有NEUTRAL) .when(col("category_set").contains("MALE"), "Male") # 规则2、5:包含FEMALE(无论是否有NEUTRAL) .when(col("category_set").contains("FEMALE"), "Female") # 规则3:仅含NEUTRAL .when(col("category_set").contains("NEUTRAL"), "Neutral") # 兜底:无有效分类的情况 .otherwise("Unknown") )
步骤4:关联回原始数据集
将推导的gender结果关联到原表,得到每条记录的gender字段:
final_df = df.join(person_gender_df, on="person", how="left") \ .select("person", "title", "gender") # 查看结果 final_df.show()
关键说明
- 规则优先级:必须先判断「同时包含MALE和FEMALE」的情况,否则会被后续单一性别规则覆盖
- 性能优化:使用Spark内置函数替代UDF,能充分利用Spark优化引擎,处理大数据量时更高效
- 扩展性:新增头衔或规则时,只需修改分类集合或
when条件即可
输出结果
运行代码后输出与示例完全一致:
+--------+--------+--------+ | person| title| gender| +--------+--------+--------+ |SYNTHE02| Mr| Male| |SYNTHE02| Dr| Male| |SYNTHE03| Mr| Male| |SYNTHE03| Mr| Male| |SYNTHE05| Mrs| Female| |SYNTHE05| Ms| Female| |SYNTHE05| Ms| Female| |SYNTHE01| Mrs| Female| |SYNTHE01| Dr| Female| |SYNTHE01| Ms| Female| |SYNTHE07| Dr| Neutral| |SYNTHE07| Prof| Neutral| |SYNTHE08| Mrs| Unknown| |SYNTHE08| Prof| Unknown| |SYNTHE08| Mr| Unknown| +--------+--------+--------+
内容的提问来源于stack exchange,提问作者SDS
相关产品推荐
相关产品推荐

