【问题标题】:PyArrow Table: Cast a Struct within a ListArray column to a new schemaPyArrow 表:将 ListArray 列中的结构转换为新模式
【发布时间】:2021-12-13 02:28:00
【问题描述】:

我有一个镶木地板文件,其中 ListArray 列中有一个结构字段,其中结构内字段的数据类型从 int 更改为带有一些新数据的浮点数。

为了合并新旧数据,我一直在使用pq.read_table 读取活动和历史镶木地板文件,然后使用pa.concat_table 合并并写入新文件。

因此,为了在连接之前使两个表的架构兼容,我执行以下操作:

active = pq.read_table("path\to\active\parquet")
active_schema = active.schema

hist = pq.read_table("path\to\hist\parquet")
hist = hist.cast(target_schema=active_schema)

combined = pa.concat_tables([active, hist])

但我在投射时收到以下错误:

ArrowNotImplementedError: Unsupported cast from struct<code: string, unit_price: struct<amount: int64, currency: string>, line_total: struct<amount: int64, currency: string>, reversal: bool, include_for: list<item: string>, quantity: int64, seats: int64, units: int64, percentage: int64> to struct using function cast_struct

基于此,我似乎无法进行演员表。

所以我的问题是,如何合并这些数据集/如何更新旧表上的架构?如果可能的话,我会尽量留在箭头/镶木地板生态系统中。

【问题讨论】:

  • 不幸的是,将结构转换为类似的结构类型但具有不同的字段类型尚未实现(请参阅issues.apache.org/jira/browse/ARROW-1888 以获得功能请求)。我认为目前唯一可能的解决方法是提取结构列,分别转换字段,从中重新创建结构列并用它更新表。

标签: python pyarrow apache-arrow


【解决方案1】:

不幸的是,尚未实现将结构转换为类似结构类型但具有不同字段类型的功能(请参阅https://issues.apache.org/jira/browse/ARROW-1888 以获取功能请求)。

我认为目前唯一可能的解决方法是提取结构列,分别转换字段,从中重新创建结构列并用它更新表。

这个工作流的一个小例子,从下面的带有结构列的表开始:

>>> table = pa.table({'col1': [1, 2, 3], 'col2': [{'a': 1, 'b': 2}, None, {'a':3, 'b':4}]})
>>> table
pyarrow.Table
col1: int64
col2: struct<a: int64, b: int64>
  child 0, a: int64
  child 1, b: int64

并假设以下目标模式(其中 struct 列的一个字段从 int 更改为 float):

>>> new_schema = pa.schema([('col1', pa.int64()), ('col2', pa.struct([('a', pa.int64()), ('b', pa.float64())]))])
>>> new_schema
col1: int64
col2: struct<a: int64, b: double>
  child 0, a: int64
  child 1, b: double

然后解决方法如下:

# cast fields separately
struct_col = table["col2"]
new_struct_type = new_schema.field("col2").type
new_fields = [field.cast(typ_field.type) for field, typ_field in zip(struct_col.flatten(), new_struct_type)]
# create new structarray from separate fields
import pyarrow.compute as pc
new_struct_array = pc.make_struct(*new_fields, field_names=[f.name for f in new_struct_type])
# replace the table column with the new array
col_idx = table.schema.get_field_index("col2")
new_table = table.set_column(col_idx, new_schema.field("col2"), new_struct_array)

>>> new_table
pyarrow.Table
col1: int64
col2: struct<a: int64, b: double>
  child 0, a: int64
  child 1, b: double

【讨论】:

  • 感谢@joris 的详细解释。我相信这会奏效,但是,当尝试实现时,我意识到它实际上是 ListArray 列中的结构,而不是实际的 Struct 列。因此,创建 new_fields 失败,因为 ListArray 模式类型不可迭代。我更新了我的问题以反映实际情况。如果您有任何其他见解,将不胜感激!
猜你喜欢
  • 1970-01-01
  • 2019-11-23
  • 1970-01-01
  • 2021-05-21
  • 2016-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多