Python中使用PyArrow/Pandas将指定列转换为Struct列并保存为Parquet文件的问题求助
看起来你已经折腾了不少方法,咱们一步步拆解解决你的问题。核心需求是把5个数值列合并成Struct列,再将1000行数据转成1行1000列的格式保存为Parquet。下面是可行的实现方案,以及你之前尝试的问题分析:
一、正确实现步骤(优先用PyArrow,能完美保留Struct结构)
1. 读取数据并合并为Struct列
直接用PyArrow把指定列打包成Struct数组,这是最直接的方式:
import pyarrow as pa import pyarrow.parquet as pq import pandas as pd # 1. 读取原始CSV数据 df = pd.read_csv('original.csv') # 转成PyArrow Table(方便后续Struct操作) source_table = pa.Table.from_pandas(df) # 2. 定义Struct类型,并将5列组合成Struct数组 struct_type = pa.struct([ pa.field('bidopen', pa.float64()), pa.field('bidclose', pa.float64()), pa.field('bidhigh', pa.float64()), pa.field('bidlow', pa.float64()), pa.field('tickqty', pa.int64()) ]) struct_array = pa.array( list(zip(source_table['bidopen'], source_table['bidclose'], source_table['bidhigh'], source_table['bidlow'], source_table['tickqty'])), type=struct_type ) # 3. 创建包含Struct列的新表(此时是1000行,1个Struct列) struct_table = pa.Table.from_arrays([struct_array], names=['data'])
2. 转换为1行1000列的格式
把1000行的Struct列转成1行的1000个Struct列,列名按data_0、data_1...data_999命名:
# 将Struct数组转为Python列表,每个元素是一个Struct字典 struct_list = struct_array.to_pylist() # 构建1行数据的字典:键是列名,值是单个Struct标量 final_columns = { f'data_{i}': pa.scalar(struct_list[i], type=struct_type) for i in range(len(struct_list)) } # 创建最终的1行1000列Table final_table = pa.Table.from_pydict(final_columns) # 保存为Parquet文件 pq.write_table(final_table, 'final_output.parquet')
二、你之前方法的问题分析
方法1:Pandas字典方式
你写错了pa.Table.from_pydict的参数格式(用了逗号{...,...}而不是冒号{...:...}),正确写法应该是:
table = pa.Table.from_pydict({'data': pa.array(df3)})
生成Table后直接用pq.write_table保存就能保留Struct结构,别用Pandas保存(Pandas会自动把Struct展开成原列)。
方法2:PyArrow创建Struct
你定义的Schema是包含list(struct)的单字段,但原table是5个独立列的表,两者Schema完全不匹配,自然写入报错。必须先把5列合并成Struct数组,再构建符合Schema的Table才能写入。
方法3:PyArrow Cast转换
Cast操作要求原表和目标Schema的字段名、数量完全匹配,你原表是5个字段,目标Schema是1个data字段,根本无法直接Cast,得先合并列。
方法4:Pandas多索引转PyArrow Schema
错误出在df.values[:, 1:]是Numpy数组,直接用它创建DataFrame时没有正确绑定多索引,而且这种方式绕远路了,不如直接用PyArrow处理Struct高效。
方法5:PySpark
其实Win10下可以用免安装的Hadoop工具包(比如winutils),不过既然你已经放弃,用PyArrow完全能搞定你的需求,不需要额外依赖。
内容的提问来源于stack exchange,提问作者alex-mon888

