PySpark技术实现:判断郊区名称是否匹配地址字段并返回匹配值
PySpark地址郊区匹配解决方案
刚好之前处理过类似的地址匹配需求,针对你给出的两个DataFrame场景,这里有一套完整的实现方案:
问题回顾
我们有两个PySpark DataFrame:
- DataFrame1:包含邮编、区域和逗号分隔的郊区列表
- DataFrame2:包含完整地址字符串
需要从完整地址中匹配到对应的郊区名称,无匹配则返回NULL。
解决方案步骤
- 拆分郊区列表:把DataFrame1中逗号分隔的郊区列拆分成单独行,每个郊区一条记录,方便后续匹配
- 统一字符格式:将郊区名称和完整地址都转成大写(或小写),避免大小写敏感导致的匹配失败
- 关联匹配:通过精确单词匹配关联两个DataFrame,保留所有完整地址记录
- 处理多匹配情况:如果一个地址匹配到多个郊区,按规则取其中一个(示例取第一个匹配项)
完整代码实现
from pyspark.sql import SparkSession from pyspark.sql.functions import explode, split, upper, regexp_extract, first, col, trim from pyspark.sql.window import Window # 初始化SparkSession spark = SparkSession.builder.appName("SuburbAddressMatcher").getOrCreate() # 创建示例DataFrame1(郊区数据) data_suburbs = [ ("2000", "Sydney", "Dawes Point, Haymarket, Millers Point, Sydney, The Rocks"), ("2001", "Sydney", "Sydney"), ("2113", "Sydney", "North Ryde") ] df_suburbs = spark.createDataFrame(data_suburbs, ["Postcode", "District", "City/ Town/ Suburb"]) # 创建示例DataFrame2(完整地址数据) data_addresses = [ ("BADAJOZ ROAD NORTH RYDE 2113, NSW, Australia",), (" HAY STREET HAYMARKET 2000, NSW, Australia ",), (" SMART STREET FAIRFIELD 2165, NSW, Australia ",), ("CLARENCE STREET SYDNEY 2000, NSW, Australia",) ] df_addresses = spark.createDataFrame(data_addresses, ["FullAddress"]) # 1. 拆分郊区列表为多行,并统一转大写 df_suburbs_exploded = df_suburbs.withColumn("suburb", explode(split(col("City/ Town/ Suburb"), ", "))) \ .withColumn("suburb_upper", upper(col("suburb"))) # 2. 处理完整地址:转大写并去除首尾空格 df_addresses_clean = df_addresses.withColumn("FullAddress_clean", upper(trim(col("FullAddress")))) # 3. 关联匹配:使用单词边界正则确保精确匹配,避免部分字符串误匹配 matched_df = df_addresses_clean.join( df_suburbs_exploded, regexp_extract(df_addresses_clean.FullAddress_clean, f"\\b{col('suburb_upper')}\\b", 0) == col("suburb_upper"), "left" ) # 4. 处理多匹配:按地址分组,取排序后的第一个匹配郊区 window_spec = Window.partitionBy("FullAddress").orderBy(col("suburb").asc()) result_df = matched_df.withColumn("matched_suburb", first("suburb").over(window_spec)) \ .groupBy("FullAddress") \ .agg(first("matched_suburb").alias("suburb")) # 展示结果 result_df.show(truncate=False)
代码说明
- 拆分郊区列:用
explode(split(...))把逗号分隔的字符串转成多行,让每个郊区单独成为一条记录,大幅降低匹配复杂度 - 格式统一:转大写+去除首尾空格,解决地址大小写不一致、前后冗余空格导致的匹配失败问题
- 精确匹配:使用
\\b单词边界正则,确保匹配的是完整的郊区名称(比如不会把"Ryde"误匹配到包含"North Ryde"的地址) - 多匹配处理:通过窗口函数按地址分组,取排序后的第一个郊区,你也可以根据需求调整排序规则(比如优先匹配和邮编一致的郊区)
运行代码后就能得到你期望的输出结果啦!
内容的提问来源于stack exchange,提问作者Ali
相关产品推荐
相关产品推荐

