You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何读写/追加含非固定结构字典的Pandas DataFrame到Parquet?

问题:PyArrow追加动态字典字段到Parquet时的类型不匹配

我们的应用需要将DataFrame片段追加到Parquet存储,但以下代码加载时会因类型不匹配失败:

import pyarrow as pa
import pyarrow.parquet as pq
import pandas as pd
df_test1 = pd.DataFrame({'a': [1, 2], 'b': [{'k1': 0, 'k2':1}, {'k3': 'ok'}]})
df_test2 = pd.DataFrame({'a': [1, None], 'b': [{'k1': None}, {'k3': None}]})
pq_dir = "/tmp/test.pq"
for _df in [df_test1, df_test2]:
    pa_data = pa.Table.from_pandas(_df)
    display(pa_data)
    pq.write_to_dataset(pa_data,root_path=pq_dir)
pd.read_parquet(pq_dir)

原因分析

df_test1转换后的表结构:

pyarrow.Table
a: double
b: struct<k1: int64, k2: int64, k3: string>
  child 0, k1: int64
  child 1, k2: int64
  child 2, k3: string

df_test2转换后的schema:

pyarrow.Table
a: double
b: struct<k1: null, k3: null>
  child 0, k1: null
  child 1, k3: null

由于字典字段b的键名、值类型完全无约束(仅要求键为字符串),无法提前定义统一的schema来匹配所有数据。

现有解决方案的局限性

方案1:全量读取合并

pd.concat(d.to_table().to_pandas() for d in pa.dataset.dataset(pq_dir).get_fragments())

该方法必须读取整个数据集,无法支持按行范围(第N到M行)读取,处理超大型数据时完全不现实。

方案2:字典转JSON存储

直接将字典序列化为JSON字符串存储,但JSON序列化/反序列化效率低,会大量浪费内存,性能表现差。

方案3:fastparquet库

fastparquet可以轻松处理该场景:

import fastparquet
df_test1 = pd.DataFrame({'a': [1., 2], 'b': [{'k1': 0, 'k2':1}, {'k3': 'ok'}]})
df_test2 = pd.DataFrame({'a': [1., None], 'b': [{'k1': None}, {'k3': None}]})
pq_dir = "/tmp/test1.pq"

for _i, _df in enumerate([df_test1, df_test2]):
    fastparquet.write(pq_dir, _df, file_scheme="hive", append=_i>0)
fastparquet.ParquetFile(pq_dir).to_pandas()

但fastparquet代码质量尚不成熟,其本质是将字典对象自动转换为纯文本JSON存储:

<pyarrow._parquet.ParquetSchema object at 0x7f6f80d9fd00>
required group field_id=-1 schema {
  optional double field_id=-1 a;
  optional binary field_id=-1 b (JSON);
}

读取时得到的是JSON字符串:

pqt = pq.read_table('/tmp/test1.pq')
pqt[1][1].as_py().decode()
# '{"k3":"ok"}'

这种方式效率极低,远不如使用jsonb或bson格式存储。

核心矛盾与疑问

PyArrow本质期望数据遵循固定schema的关系型模型,尽管Parquet本身支持schema演进。值得注意的是,PyArrow的R API中concat_table提供了unify_schema=True的选项,但Python API并未暴露该功能,存在明显的功能缺失。

PyArrow无法像多数类SQL数据库那样良好处理单元格内的字典或数组类型。那么,对于需要非关系型数据模型的场景,PyArrow是不是一个不合适的选择?


内容的提问来源于stack exchange,提问作者Wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 04:24:55