扩展数据框

子类 DataFrame

有一些项目是Pandas对象的子类或复制了Pandas对象的功能:

  • GeoPandas: 用于地理空间分析

  • cuDF: 用于GPU上的数据分析

这些项目可能也希望使用 Dask 生成自身的并行变体,并且可能希望重用 Dask DataFrame 中的一些代码。子类化 Dask DataFrames 旨在供这些库的维护者使用,而不是供一般用户使用。

实现 dask、name、meta 和 divisions

您需要按照 DataFrame 设计文档 中的定义实现 ._meta.dask.divisions._name

扩展分派方法

如果你打算传递类似于 Pandas 的对象,但它们不是普通的 Pandas 对象,那么我们要求你扩展一些分派方法:make_metaget_collection_typeconcat

make_meta

此函数返回您的一个非Dask对象的空版本,给定一个非空的非Dask对象:

from dask.dataframe.dispatch import make_meta_dispatch

@make_meta_dispatch.register(MyDataFrame)
def make_meta_dataframe(df, index=None):
    return df.head(0)


@make_meta_dispatch.register(MySeries)
def make_meta_series(s, index=None):
    return s.head(0)


@make_meta_dispatch.register(MyIndex)
def make_meta_index(ind, index=None):
    return ind[:0]

为了将任意 对象 类型分派到相应的后端,我们建议为 make_meta_obj 注册一个分派:

from dask.dataframe.dispatch import make_meta_obj

@make_meta_obj.register(MyDataFrame)
def make_meta_object(x, index=None):
    if isinstance(x, dict):
        return MyDataFrame()
    elif isinstance(x, int):
        return MySeries
    .
    .
    .

此外,你应该创建一个类似的函数,该函数返回填充了少量代表性或随机数据的非空版本的非Dask DataFrame对象。这在未提供类型时用于猜测类型。它应该期望一个带有列、dtypes、索引名的空版本对象,并返回一个非空版本:

from dask.dataframe.utils import meta_nonempty

@meta_nonempty.register(MyDataFrame)
def meta_nonempty_dataframe(df):
    ...
    return MyDataFrame(..., columns=df.columns,
                       index=MyIndex(..., name=df.index.name)


@meta_nonempty.register(MySeries)
def meta_nonempty_series(s):
    ...


@meta_nonempty.register(MyIndex)
def meta_nonempty_index(ind):
    ...

get_collection_type

给定一个非 Dask 的 DataFrame 对象,返回其 Dask 等价对象:

from dask.dataframe import get_collection_type

@get_collection_type.register(MyDataFrame)
def get_collection_type_dataframe(df):
    return MyDaskDataFrame


@get_collection_type.register(MySeries)
def get_collection_type_series(s):
    return MyDaskSeries


@get_collection_type.register(MyIndex)
def get_collection_type_index(ind):
    return MyDaskIndex

连接

将您的多个非Dask DataFrame对象连接在一起。它应该接受一个对象列表(同质类型):

from dask.dataframe.methods import concat_dispatch

@concat_dispatch.register((MyDataFrame, MySeries, MyIndex))
def concat_pandas(dfs, axis=0, join='outer', uniform=False, filter_warning=True):
    ...

扩展数组

与其子类化 Pandas DataFrame,你可能对使用 扩展数组 来扩展 Pandas 感兴趣。

所有第一方扩展数组(那些在 pandas 本身中实现的)都直接由 dask 支持。

实现第三方扩展数组(pandas 之外)的开发者需要将他们的 ExtensionDtype 注册到 Dask,以便在 dask.dataframe 中正确工作。

例如,我们将注册来自 pandas 测试套件的 仅测试 DecimalDtype

from decimal import Decimal
from dask.dataframe.extensions import make_array_nonempty, make_scalar
from pandas.tests.extension.decimal import DecimalArray, DecimalDtype

@make_array_nonempty.register(DecimalDtype)
def _(dtype):
    return DecimalArray._from_sequence([Decimal('0'), Decimal('NaN')],
                                       dtype=dtype)


@make_scalar.register(Decimal)
def _(x):
   return Decimal('1')

在内部,Dask 将使用这个来创建一个用于跟踪操作中元数据的小型虚拟 Series。

>>> make_array_nonempty(DecimalDtype())
<DecimalArray>
[Decimal('0'), Decimal('NaN')]
Length: 2, dtype: decimal

因此,您(或您的用户)现在可以创建并存储一个包含扩展数组的 dask DataFrameSeries

>>> from decimal import Decimal
>>> import dask.dataframe as dd
>>> import pandas as pd
>>> from pandas.tests.extension.decimal import DecimalArray
>>> s = pd.Series(DecimalArray([Decimal('0.0')] * 10))
>>> ds = dd.from_pandas(s, 3)
>>> ds
Dask Series Structure:
npartitions=3
0    decimal
4        ...
8        ...
9        ...
dtype: decimal
Dask Name: from_pandas, 3 tasks

注意 decimal 数据类型。

访问器

许多扩展数组通过访问器在 Series 或 DataFrame 对象上暴露其功能。Dask 提供了装饰器来注册类似于 pandas 的访问器。更多信息请参见 pandas 关于访问器的文档

dask.dataframe.extensions.register_dataframe_accessor(name)[源代码]

dask.dataframe.DataFrame 上注册一个自定义访问器。

更多信息请参见 pandas.api.extensions.register_dataframe_accessor()

dask.dataframe.extensions.register_series_accessor(name)[源代码]

dask.dataframe.Series 上注册一个自定义访问器。

更多信息请参见 pandas.api.extensions.register_series_accessor()

dask.dataframe.extensions.register_index_accessor(name)[源代码]

dask.dataframe.Index 上注册一个自定义访问器。

更多信息请参见 pandas.api.extensions.register_index_accessor()