AWS Wrangler保存Parquet时自动生成冗余字典值的问题
问题描述
在Glue项目中使用AWS Wrangler时遇到如下问题:
构造包含列表列“A”的DataFrame,通过apply()将列“A”转换为仅含对应键值对(值为True)的formatted_data字典列。但使用wr.s3.to_parquet()将DataFrame保存到S3后,formatted_data列被自动转换为包含所有可能键(未出现的键设为None)的结构,而非原有的字典格式。
原始数据构造代码:
data = {'A': [['1A', '5A'], ['1A', '19A'], ['1A', '26A'], ['2A', '4A']]} df = pd.DataFrame(data)
转换后DataFrame输出:
A formatted_data 0 [1A, 5A] {"1A": True, "5A": True} 1 [1A, 19A] {"1A": True, "19A": True} 2 [1A, 26A] {"1A": True, "26A": True} 3 [2A, 4A] {"2A": True, "4A": True}
保存代码:
wr.s3.to_parquet( df=my_df, path=f"s3://{path}", dataset=True )
保存后formatted_data列异常示例:
[{'19A': None, '1A': 'true', '26A': None, '2A': None, '3A': None, '4A': None, '5A': None},{'19A': None, '1A': None, '26A': None, '2A': None, '3A': None, '4A': None, '5A': 'true'}]
原因分析
- Parquet schema统一机制:当启用
dataset=True时,AWS Wrangler会自动收集全量数据的字段信息,统一生成数据集的schema。字典类型的列会被推断为Parquet的struct类型,所有出现过的键都会成为struct的固定字段,缺失对应键的行就会用None填充。 - 类型映射差异:Pandas中的字典默认会被映射为Parquet的struct类型,而非嵌套的map类型。struct要求每行结构完全一致,因此会自动补全所有可能的字段。
解决方法
方法1:将字典转为JSON字符串保存
保存前把formatted_data列转为JSON字符串,读取时再解析回字典,避免schema推断干扰:
import json # 转换为JSON字符串 df['formatted_data'] = df['formatted_data'].apply(json.dumps) wr.s3.to_parquet( df=df, path=f"s3://{path}", dataset=True ) # 读取时还原为字典 read_df = wr.s3.read_parquet(path=f"s3://{path}", dataset=True) read_df['formatted_data'] = read_df['formatted_data'].apply(json.loads)
方法2:显式指定schema为map类型
通过Spark Schema强制将formatted_data列为map类型,避免被推断为struct:
from pyspark.sql.types import StructType, StructField, ArrayType, StringType, MapType # 定义Spark Schema schema = StructType([ StructField("A", ArrayType(StringType()), nullable=False), StructField("formatted_data", MapType(StringType(), StringType()), nullable=False) ]) # 转换为Spark DataFrame后保存 spark_df = spark.createDataFrame(df, schema=schema) wr.s3.to_parquet( df=spark_df, path=f"s3://{path}", dataset=True )
方法3:关闭schema统一(不推荐)
若不需要数据集schema一致,可关闭自动推断并使用追加模式,但会导致后续读取时schema混乱,仅适用于临时场景:
wr.s3.to_parquet( df=df, path=f"s3://{path}", dataset=True, mode="append", infer_schema=False )
内容的提问来源于stack exchange,提问作者Haggerman Swaggerman
相关产品推荐
相关产品推荐

