如何在PySpark中将含键值对的列拆分为多列?
使用PySpark转换CSV数据格式
我们可以通过数据清洗、解析键值对、长表转宽表三个核心步骤完成需求,以下是完整实现:
1. 初始化Spark并读取CSV
from pyspark.sql import SparkSession from pyspark.sql.functions import split, explode, regexp_replace, col, cast # 初始化SparkSession spark = SparkSession.builder.appName("ClassDataTransform").getOrCreate() # 读取CSV文件(替换为你的文件路径) df = spark.read.csv("input.csv", header=True, inferSchema=True)
2. 清洗并解析classes列
注意输入数据存在格式不一致问题:部分行用冒号替代逗号分隔不同键值对(比如0:0.1,1:0.5:2:0.4),需先统一格式再解析:
# 修复格式错误:把键值对之间的冒号替换为逗号(仅保留键值内部的冒号) cleaned_df = df.withColumn("classes_clean", regexp_replace(col("classes"), "(?<=\d)\:(?=\d)", ",")) # 拆分键值对为数组,再展开为多行 exploded_df = cleaned_df.withColumn("class_pair", split(col("classes_clean"), ",")) \ .select("row_num", explode(col("class_pair")).alias("pair")) # 将每个键值对拆分为class_id和分数,并转换为对应类型 parsed_df = exploded_df.withColumn("class_id", split(col("pair"), ":")[0].cast("int")) \ .withColumn("score", split(col("pair"), ":")[1].cast("double")) \ .drop("pair")
3. 长表转宽表(Pivot)
# 按row_num分组,将class_id转为列名,提取对应分数 final_df = parsed_df.groupBy("row_num") \ .pivot("class_id", [0, 1, 2]) \ .max("score") \ .withColumnRenamed("0", "class_0") \ .withColumnRenamed("1", "class_1") \ .withColumnRenamed("2", "class_2") # 查看转换结果 final_df.show()
4. (可选)保存结果到CSV
final_df.write.csv("output.csv", header=True, mode="overwrite")
关键说明
regexp_replace用于修复数据格式错误,避免解析失败;pivot操作时指定[0,1,2]可保证列顺序固定,不会因数据顺序变化乱序;- 类型转换确保
class_id为整数、score为浮点数,避免后续操作出现类型异常。
内容的提问来源于stack exchange,提问作者suraj jadhav
相关产品推荐
相关产品推荐

