PySpark将DataFrame字符串转为字典时任务失败的问题求助
PySpark JSON字符串转键值字典并转换数值类型解决方案
问题场景
原始PySpark DataFrame数据:
data = [(123, '[{"FLD_NAME":"A","FLD_VAL":"0.1"},{"FLD_NAME":"B","FLD_VAL":"0.2"},{"FLD_NAME":"C","FLD_VAL":"0.3"},{"FLD_NAME":"D","FLD_VAL":"0.4"}]')] ar = spark.createDataFrame(data, ['id', 'val'])
| id | val |
|---|---|
| 123 | [{"FLD_NAME":"A","FLD_VAL":"0.1"},{"FLD_NAME":"B","FLD_VAL":"0.2"},{"FLD_NAME":"C","FLD_VAL":"0.3"},{"FLD_NAME":"D","FLD_VAL":"0.4"}] |
目标是将val列转换为键值对字典,同时把FLD_VAL转为数值类型,最终结果:
| id | val |
|---|---|
| 123 | {"A": 0.1, "B": 0.2, "C": 0.3,"D": 0.4} |
错误原因分析
你提供的代码报错TypeError: string indices must be integers,核心问题是:
row[1]是JSON格式的字符串,不是可迭代的字典列表func直接遍历该字符串时,会把每个字符当作遍历元素,字符只能用整数索引,因此访问row['FLD_NAME']会触发错误
解决方案
方案1:使用PySpark内置函数(推荐,避免RDD转换,效率更高)
利用from_json解析JSON字符串,transform转换数值类型,map_from_entries生成字典:
from pyspark.sql import functions as F from pyspark.sql.types import StructType, StructField, StringType, FloatType # 定义JSON数组的Schema json_schema = StructType([ StructField("FLD_NAME", StringType(), nullable=False), StructField("FLD_VAL", StringType(), nullable=False) ]) # 分步处理 result_df = ar.withColumn( # 将JSON字符串解析为数组结构 "val_parsed", F.from_json(F.col("val"), json_schema) ).withColumn( # 转换每个元素的FLD_VAL为数值类型,生成(键, 值)对数组 "val_transformed", F.transform( F.col("val_parsed"), lambda x: (x["FLD_NAME"], F.cast(x["FLD_VAL"], FloatType())) ) ).withColumn( # 将(键, 值)数组转为字典 "val", F.map_from_entries(F.col("val_transformed")) ).drop("val_parsed", "val_transformed") # 清理中间列 result_df.show(truncate=False)
方案2:修复RDD方式的代码
先通过json.loads解析JSON字符串为Python列表,再处理键值对:
import json def func(json_str): # 先解析JSON字符串为字典列表 rows = json.loads(json_str) # 转换FLD_VAL为float,生成目标字典 return {row['FLD_NAME']: float(row['FLD_VAL']) for row in rows} # 移除不必要的groupByKey(原始数据每个id唯一,无需分组) arr = ar.rdd.map(lambda row: (row[0], func(row[1]))).toDF(["id", "val"]) arr.show(truncate=False)
内容的提问来源于stack exchange,提问作者dontgimmehope
相关产品推荐
相关产品推荐

