如何在dask数据帧中使用pyarrow将自定义类序列化为结构?

时间:2019-01-11 15:18:29

标签: python parquet dask pyarrow

我有一个dask数据框,它的列类型为List [MyClass]。我想将此数据帧保存到镶木地板文件中。 Dask使用pyarrow作为后端,但仅支持基本类型。

import pandas as pd
import dask.dataframe as dd


class MyClass:

    def __init__(self, a):
        self.a = a


def transform(v):
    return [MyClass(v)]


a = [[1], [2], [3]]
pdf = pd.DataFrame.from_dict(a)
ddf = dd.from_pandas(pdf, npartitions=1)
result = ddf.assign(mycol=ddf[0].apply(transform))
result.to_parquet('my_parquet.parquet')

因此,当我尝试保存它时,出现此错误:

ArrowInvalid: Error inferring Arrow data type for collection of Python objects. Got Python object of type MyClass but can only handle these types: bool, float, integer, date, datetime, bytes, unicode, decimal

很明显,我必须将MyClass转换为pyarrow兼容的结构类型,但是我找不到方法。 Pyarrow&dask具有一些序列化功能(例如https://arrow.apache.org/docs/python/ipc.html#serializing-custom-data-types),但似乎并不是我所需要的。

1 个答案:

答案 0 :(得分:1)

有点晚了,但是也许link可以帮助别人。

基本上,这取决于定义定制的手工序列化函数。例如,这是您的课程:

class MyData:
    def __init__(self, name, data):
        self.name = name
        self.data = data

您编写的函数可以与此类进行转换,例如:

def _serialize_MyData(val):
    return {'name': val.name, 'data': val.data}

def _deserialize_MyData(data):
    return MyData(data['name'], data['data']

然后从这些函数初始化上下文,以稍后提供给序列化/反序列化方法:

context = pa.SerializationContext()
context.register_type(MyData, 'MyData',
                      custom_serializer=_serialize_MyData,
                      custom_deserializer=_deserialize_MyData)

现在,您调用serialize / deserialize方法并将其传递给上下文:

buf = pa.serialize(val, context=context).to_buffer()
restored_val = pa.deserialize(buf, context=context)