Python处理含浮点列表的嵌套字典 提取单值适配Spark Parquet格式
核心问题原因
你输出的是数组类型,是因为nested_dict_w_list['outer_dict']['inner_dict']中每个元素本身就是单元素列表,你直接取索引得到的是整个列表而非内部的浮点数值,只要在取值时额外加[0]提取列表第一个元素即可。
优雅高效的实现方案
方案1:Python侧优化(适配你当前循环实现的场景)
首先预提取内层列表避免重复字典查找,再用zip遍历+生成器表达式,内存占用远低于普通列表和手动索引循环,同时修复你原有代码中range(len(array2_int)-1)少遍历最后一个元素的bug:
# 提前提取内层列表,减少循环内重复字典查找开销 inner_list = nested_dict_w_list['outer_dict']['inner_dict'] # 生成器为惰性计算,百万级数据也不会占用过多内存,可直接喂给Spark转DataFrame final_out = ((user_str, int_val, inner_list[int_val][0]) for user_str, int_val in zip(array1_str, array2_int))
如果需要显式生成列表,把外层括号换成方括号即可。
方案2:Spark侧直接处理(效率最高,适配最终存parquet的场景)
既然你最终要转Spark DataFrame存parquet,完全可以把逻辑放到Spark侧执行,避免Python侧循环的额外开销:
from pyspark.sql import SparkSession from pyspark.sql.functions import col spark = SparkSession.builder.appName("process_data").getOrCreate() # 1. 生成用户ID、索引值的DataFrame df1 = spark.createDataFrame(zip(array1_str, array2_int), schema=["user_str", "int_val"]) # 2. 拍平内层列表得到纯浮点值,生成带索引的映射表 inner_flat = [x[0] for x in nested_dict_w_list['outer_dict']['inner_dict']] df_inner = spark.createDataFrame([(idx, val) for idx, val in enumerate(inner_flat)], schema=["idx", "double_val"]) # 3. 用索引关联得到最终表,直接写入parquet时double_val就是double类型 df_final = df1.join(df_inner, df1.int_val == df_inner.idx, how="left").select("user_str", "int_val", "double_val") df_final.write.parquet("output.parquet")
优化注意点
- 不要在循环内重复做多层字典查找,提前把公共的内层列表提取为独立变量,数据量越大性能提升越明显
- 避免手动用
range(len())遍历,zip可以同时遍历多个等长序列,代码更简洁也不容易出现索引越界的bug - 百万级数据尽量用惰性计算的生成器,不要一次性把所有数据加载到Python内存中
- 尽量把数据处理逻辑和你最终用的Spark框架对齐,减少跨进程的数据传输开销
内容的提问来源于stack exchange,提问作者user7343922
相关产品推荐
相关产品推荐

