如何用 PyArrow 读取 Parquet 时控制 dictionary、binary 和 list 列的类型
2026/9/14 17:06:53 网站建设 项目流程

如何用 PyArrow 读取 Parquet 时控制 dictionary、binary 和 list 列的类型

【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow

用 PyArrow 读取 Parquet 文件时,默认行为是:Parquet 的BYTE_ARRAY列读成 Arrow 的binary类型,Parquet 的LIST列读成 Arrow 的list类型,两者都使用 32 位偏移量;数据量很大时偏移量可能溢出。字符串列也默认按string读入,即使值大量重复也不会自动走字典编码。PyArrow 在read_tableParquetFileParquetDataset上提供了read_dictionarybinary_typelist_type三个读取参数,让你可以在读取时选择目标类型。本文基于 PyArrow 官方文档 Data Type Handling 与 Reading and Writing Single Files 说明这三个参数怎么用、如何验证结果,以及一个关键限制:文件元数据中若已存储 Arrow schema,后两个参数会失效。

前提:环境已安装pyarrow,且已有一个待读取的本地 Parquet 文件。下面代码中的文件路径(如example.parquet)均会写入当前工作目录,可按需替换。

用 read_dictionary 把指定列读成 DictionaryArray

read_dictionary选项接受一个列名列表,命中的列会被读成DictionaryArray;如果随后转成 pandas,对应列会变成pandas.Categorical。这个选项只对字符串和 binary 列类型有效,对于有大量重复字符串值的列,它可以明显降低内存占用并提升性能。

按文档示例,先写入一张表,再用read_dictionary读取(以下输出为文档示例):

>>> import pyarrow as pa >>> import pyarrow.parquet as pq >>> table = pa.table({'one': [-1, None, 2.5], ... 'two': ['foo', 'bar', 'baz'], ... 'three': [True, False, True]}) >>> pq.write_table(table, 'example.parquet') >>> pq.read_table('example.parquet', read_dictionary=['two']) pyarrow.Table one: double two: dictionary<values=string, indices=int32, ordered=0> three: bool ---- one: [[-1,null,2.5]] two: [ -- dictionary: ["foo","bar","baz"] -- indices: [0,1,2]] three: [[true,false,true]]

判断标准:输出的 schema 中,指定列的类型显示为dictionary<values=string, indices=int32, ordered=0>,而不是string,即表示该列按DictionaryArray读入。同一个参数也可以传给ParquetFile构造函数,见 parquet_type_handling.rst 中提到的read_tableParquetDataset均支持该选项;ParquetFile参数说明见 core.py。

用 binary_type 控制 BYTE_ARRAY 列的 Arrow 类型

binary_type用于把 Parquet 的BYTE_ARRAY列读成你指定的 Arrow 类型,文档列出的可选值为pa.binary()(默认)、pa.large_binary()pa.binary_view()。改用 64 位偏移的large_binary可避免超大数据集上的偏移量溢出。文档示例:

>>> table = pa.table({'data': pa.array([b'hello', b'world'], pa.binary())}) >>> pq.write_table(table, 'binary.parquet', store_schema=False) >>> pq.read_table('binary.parquet', binary_type=pa.large_binary()).schema data: large_binary

读出的 schema 中该列显示data: large_binary,即表示binary_type生效。注意示例写入时显式传了store_schema=False,原因见下文「store_schema 限制」。

用 list_type 控制 LIST 列的 Arrow 类型

list_type接受pa.ListTypepa.LargeListType,把 Parquet 的LIST列读成对应的列表类型。同样以large_list(64 位偏移)为例(输出为文档示例):

>>> table = pa.table({'lists': pa.array([[1, 2], [3]], pa.list_(pa.int32()))}) >>> pq.write_table(table, 'lists.parquet', store_schema=False) >>> pq.read_table('lists.parquet', list_type=pa.LargeListType).schema lists: large_list<element: int32> child 0, element: int32

schema 显示large_list<element: int32>即表示按LargeListType读入。

关键限制:store_schema=True 时两个参数被忽略

文档明确说明:当 Parquet 文件元数据中存在序列化的 Arrow schema(即写入时store_schema=True)时,binary_typelist_type都会被忽略。而write_tablestore_schema默认值就是True(见 core.py),所以如果你直接pq.write_table(table, 'x.parquet')再读取,binary_type/list_type不会起作用。

因此,想让这两个参数生效,读取方(PyArrow 之外)或本文件必须满足「元数据中没有 Arrow schema」这一条件。用 PyArrow 自己生成测试文件时,像文档示例那样写入store_schema=False即可。反过来,read_dictionary不受这条限制影响,它在有 Arrow schema 的文件上依然有效。

如果你读取的是外部工具生成的 Parquet 文件,判断顺序是:先看 schema 中目标列当前显示的类型(如binary/list),再决定是否需要binary_type/list_type;若传参后类型没有变化,检查该文件元数据里是否带有序列化 Arrow schema,带有的话这两个参数对该文件无效。

验证方式汇总

三种类型控制都可以通过读取后检查 schema 来核对,无需转成 pandas:

t = pq.read_table('example.parquet', read_dictionary=['two']) print(t.schema) # two 应为 dictionary<...> t = pq.read_table('binary.parquet', binary_type=pa.large_binary()) print(t.schema) # data 应为 large_binary t = pq.read_table('lists.parquet', list_type=pa.LargeListType) print(t.schema) # lists 应为 large_list<element: int32>

也可以用pq.ParquetFile(path, read_dictionary=[...], binary_type=..., list_type=...)构造读取器后调.read().schema,参数在ParquetFile构造函数中均可用(见 core.py)。

限制与边界

  • read_dictionary只对字符串和 binary 列类型有效,其他类型的列不要放进该列表。
  • binary_type仅支持文档列出的三种值:pa.binary()pa.large_binary()pa.binary_view()list_type仅支持pa.ListTypepa.LargeListType
  • binary_typelist_type在文件元数据含序列化的 Arrow schema(store_schema=True写入)时不生效,这是文档明确给出的行为,不是配置遗漏。
  • 对分区数据集(ParquetDataset),文档提示分区列在加载时会转成 Arrow dictionary 类型(pandas categorical),这是读取数据集时的固有行为,与read_dictionary参数无关,见 parquet_datasets.rst。

【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询