【问题标题】:Parquet `write_table` introduces keys of data type to the data when writing to output fileParquet `write_table` 在写入输出文件时将数据类型的键引入数据
【发布时间】:2021-06-19 00:25:57
【问题描述】:

将数据写入镶木地板文件时遇到问题。我尝试了不同的pyarrow 版本(2.0 和 3.0),但结果看起来一样。

我的数据外观示例:

test_data = {
    'dogs': [
        {'dog': 'frankie'},
        {'dog': 'ricky'}
    ]
}

other_test_data = {
    'dogs': [
        {'dog': 'rory'},
        {'dog': 'marko'}
    ]
}

然后,我将它们重新格式化为如下所示:

dog_data = {
    'dogs': [
        [{
            'dog': 'frankie'
        }, {
            'dog': 'ricky'
        }],
        [{
            'dog': 'rory'
        }, {
            'dog': 'marko'
        }]
    ]
}

我定义了架构:

dog_fields = [
    pa.field('dog', pa.string(), nullable=True)
]

dog_schema = pa.schema([
        ('dogs', pa.list_(pa.struct(dog_fields)))
    ])

我使用以下方法将它们转换为 pyarrow.Table: pq_table = pa.Table.from_pydict(mapping=dog_data, schema=dog_schema)

最后,我写入一个文件: pq.write_table(pq_table, 'dog_data.parquet')

我在文件中看到的是这个,称为listitem 的附加键:

{
    "dogs": {
        "list": [{
            "item": {
                "dog": "frankie"
            }
        }, {
            "item": {
                "dog": "ricky"
            }
        }]
    }
}

谁能解释一下为什么将数据字段的类型添加为数据的键?

有办法解决吗?


编辑

这就是我使用listitem 字段获取数据的方式。 我用brew install parquet-tools安装包,然后运行:

parquet-tools cat --json dog_data.parquet

我选择这样加载文件的原因是我想检查内容是什么。需求来自我在将数据从镶木地板文件加载到 BigQuery 时看到的损坏的架构。 BigQuery 不理解数据的结构,并将架构解释如下:

烦人的.list.item 东西都加在那里了。

【问题讨论】:

    标签: google-bigquery parquet pyarrow


    【解决方案1】:

    您如何获得带有附加列表/项目的字典?

    据我所知,将您的数据转换为 arrow.Table,将其保存到 parquet 并重新加载会产生相同的结果:

    table = pa.Table.from_pydict(mapping=dog_data, schema=dog_schema)
    pq.write_table(table, 'dog_data.parquet')
    loaded_table = pq.read_table('dog_data.parquet')
    
    print(loaded_table.to_pydict() == dog_data)
    >>> True
    print (loaded_table.to_pydict())
    >>> {'dogs': [[{'dog': 'frankie'}, {'dog': 'ricky'}], [{'dog': 'rory'}, {'dog': 'marko'}]]}
    

    【讨论】:

    • 对不起,我应该提到我是如何得到它的:我从命令行使用parquet-tools 来查看文件的内容。我这样做的原因是看看那里写了什么;最终目标是自动将此数据从 parquet 文件加载到 BigQuery,这会导致加载数据时架构损坏。令人讨厌的是,BQ 不明白如何避免和解释这个列表和项目键,只是将它们与原始名称一起加载。感觉就像一个 BQ api 问题 tbh,因为 pyarrow 可以毫无问题地重新加载它们,正如您所展示的那样。
    • 我的意思是我最终会得到这样的东西:github.com/googleapis/python-bigquery/issues/…,额外的listitem 键名。抱歉,如果现在这似乎是一个不同的问题,但它使我得出结论,它必须是 BQ。
    • 您能否通过使用 parquet-tools 复制输出的步骤更新您的问题
    • cloud.google.com/bigquery/docs/… BQ 将所有嵌套组转换为结构。 pyarrow 使用的 parquet three grouping levels 中列表的规范编码。
    • @MicahKornfield 我不确定我是否理解您的建议。 BQ 确实将组转换为结构,但它错误地在变量名称中添加了其他内容。在我的示例中,我希望使用名称 dogsdogs.dog,而不是现在得到的 dogs.listdogs.list.item.dog。 BQ读取这些数据的方式一定有问题。为什么会在原来的字段名后面加上listitem
    【解决方案2】:

    @christinabo 这里的问题是,在 Parquet 中表示列表的规范方法是使用 three groups for a single list。外部组具有用户指定的名称。这两个内部组被称为“列表”和“元素”。 pyarrow 默认使用“item”而不是“element”。所以 BQ 忽略了嵌套组是一种逻辑类型这一事实。

    Enable List Inference Parameter 的行为在某种程度上是可控的

    (完全披露我为 BQ 和 Arrow 工作)

    【讨论】:

      【解决方案3】:

      您需要使用 parquet 文件编写 pq.write_table(pq_table, 'dog_data.parquet', use_compliant_nested_type=True)

      https://arrow.apache.org/docs/python/generated/pyarrow.parquet.write_table.html#pyarrow.parquet.write_table

      【讨论】:

        猜你喜欢
        • 2022-01-04
        • 2019-07-03
        • 1970-01-01
        • 2020-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-24
        • 2022-01-17
        相关资源
        最近更新 更多