如何通过 pyarrow 使用用户定义的模式编写 Parquet

How to write Parquet with user defined schema through pyarrow

当我执行以下代码时 - 出现以下错误 ValueError:Table 架构与用于创建文件的架构不匹配 .

import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq


fields = [
    ('one', pa.int64()),
    ('two', pa.string(), False),
    ('three', pa.bool_())
]
schema = pa.schema(fields)

schema = schema.remove_metadata()
df = pd.DataFrame(
    {
        'one': [2, 2, 2],
        'two': ['foo', 'bar', 'baz'],
        'three': [True, False, True]
    }
)

df['two'] = df['two'].astype(str)

table = pa.Table.from_pandas(df, schema, preserve_index=False).replace_schema_metadata()
writer = pq.ParquetWriter('parquest_user_defined_schema.parquet', schema=schema)
writer.write_table(table)

这适用于最新版本的 pyarrow (>=0.14.0),但我可以确认我也遇到了 pyarrow 0.13 的错误。

原因是在从 pandas 到箭头(参见 https://issues.apache.org/jira/browse/ARROW-5169)的转换中没有保留架构的可空性的错误。

使用 pyarrow 0.13:

>>> schema.field_by_name('two').nullable
False

>>> table.schema.field_by_name('two').nullable
True

这使得您指定的 schema 和传递给 write_table 的 table 的模式不匹配,给出了您看到的错误。
这在 0.14 中已修复,两者都会在上面的输出中给出 False

因此您可以在手动创建架构时删除 nullable=False,或者更新为箭头 >= 0.14。


请注意,您正在将单个 table 写入单个 parquet 文件,您不需要手动指定架构(您在将 pandas DataFrame 转换为箭头时已经指定了它Table,而 pyarrow 将使用 table 的模式写入 parquet)。所以在简单的情况下,你也可以这样做:

pq.write_table(table, 'parquest_user_defined_schema.parquet')

附加说明:您需要 writer.close() 才能使您的示例完整。