jua*_*ino 9 python dataframe pandas parquet pyarrow
我正在尝试将 Python Pandas DataFrame 存储为 Parquet 文件,但遇到了一些问题。我的 Pandas DF 的一列包含这样的字典:
import pandas as pandas
df = pd.DataFrame({
"ColA": [1, 2, 3],
"ColB": ["X", "Y", "Z"],
"ColC": [
{ "Field": "Value" },
{ "Field": "Value2" },
{ "Field": "Value3" }
]
})
df.to_parquet("test.parquet")
Run Code Online (Sandbox Code Playgroud)
现在,这工作得很好,问题是当字典的嵌套值之一具有与其他值不同的类型时。例如:
import pandas as pandas
df = pd.DataFrame({
"ColA": [1, 2, 3],
"ColB": ["X", "Y", "Z"],
"ColC": [
{ "Field": "Value" },
{ "Field": "Value2" },
{ "Field": ["Value3"] }
]
})
df.to_parquet("test.parquet")
Run Code Online (Sandbox Code Playgroud)
这会引发以下错误:
ArrowInvalid: ('cannot mix list and non-list, non-null values', 'Conversion failed for column ColC with type object')
请注意,对于 DF 的最后一行,字典Field
的属性ColC
是列表而不是字符串。
是否有任何解决方法可以将此 DF 存储为 Parquet 文件?
ColC
是一种 UDT(用户定义类型),具有一个名为Field
类型 的字段Union of String, List of String
。
理论上arrow支持它,但实际上很难弄清楚它的类型是什么ColC
。即使您显式提供数据框的架构,它也不起作用,因为尚不支持这种类型的转换(将联合从 pandas 转换为 arrow/parquet)。
union_type = pa.union(
[pa.field("0",pa.string()), pa.field("1", pa.list_(pa.string()))],
'dense'
)
col_c_type = pa.struct(
[
pa.field('Field', union_type)
]
)
schema=pa.schema(
[
pa.field('ColA', pa.int32()),
pa.field('ColB', pa.string()),
pa.field('ColC', col_c_type),
]
)
df = pd.DataFrame({
"ColA": [1, 2, 3],
"ColB": ["X", "Y", "Z"],
"ColC": [
{ "Field": "Value" },
{ "Field": "Value2" },
{ "Field": ["Value3"] }
]
})
pa.Table.from_pandas(df, schema)
Run Code Online (Sandbox Code Playgroud)
这会给你这个错误:
('Sequence converter for type union[dense]<0: string=0, 1: list<item: string>=1> not implemented', 'Conversion failed for column ColC with type object'
即使您手动创建箭头表,它也无法将其转换为镶木地板(同样,不支持联合)。
import io
import pyarrow.parquet as pq
col_a = pa.array([1, 2, 3], pa.int32())
col_b = pa.array(["X", "Y", "Z"], pa.string())
xs = pa.array(["Value", "Value2", None], type=pa.string())
ys = pa.array([None, None, ["value3"]], type=pa.list_(pa.string()))
types = pa.array([0, 0, 1], type=pa.int8())
col_c = pa.UnionArray.from_sparse(types, [xs, ys])
table = pa.Table.from_arrays(
[col_a, col_b, col_c],
schema=pa.schema([
pa.field('ColA', col_a.type),
pa.field('ColB', col_b.type),
pa.field('ColC', col_c.type),
])
)
with io.BytesIO() as buffer:
pq.write_table(table, buffer)
Run Code Online (Sandbox Code Playgroud)
Unhandled type for Arrow to Parquet schema conversion: sparse_union<0: string=0, 1: list<item: string>=1>
Run Code Online (Sandbox Code Playgroud)
我认为现在您唯一的选择是使用一个结构,其中字段的字符串值和字符串值列表具有不同的名称。
df = pd.DataFrame({
"ColA": [1, 2, 3],
"ColB": ["X", "Y", "Z"],
"ColC": [
{ "Field1": "Value" },
{ "Field1": "Value2" },
{ "Field2": ["Value3"] }
]
})
df.to_parquet('/tmp/hello')
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
17772 次 |
最近记录: |