pandas:链式方法(如.resample()、. rolling()等)的组成

时间:2018-07-11 07:29:28

标签: python pandas chained object-composition

我想构建pandas.DataFrame的扩展名-我们将其称为SPDF-该扩展名可以超越简单的DataFrame可以做的事情:

import pandas as pd
import numpy as np


def to_spdf(func):
    """Transform generic output of `func` to SPDF.

    Returns
    -------
    wrapper : callable
    """
    def wrapper(*args, **kwargs):
        res = func(*args, **kwargs)
        return SPDF(res)

    return wrapper


class SPDF:
    """Special-purpose dataframe.

    Parameters
    ----------
    df : pandas.DataFrame

    """

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

    def __repr__(self):
        return repr(self.df)

    def __getattr__(self, item):
        res = getattr(self.df, item)

        if callable(res):
            res = to_spdf(res)

        return res


if __name__ == "__main__":

    # construct a generic SPDF
    df = pd.DataFrame(np.eye(4))
    an_spdf = SPDF(df)

    # call .diff() to obtain another SPDF
    print(an_spdf.diff())

现在,DataFrame的方法返回了另一个DataFrame,例如上面的MWE中的.diff(),还给了我另一个SPDF,这很棒。但是,我还想欺骗诸如.resample('M').last().rolling(2).mean()之类的链接方法,最终产生SPDF。到目前为止,我已经失败了,因为.rolling()之类的类型为callable,而我的包装器to_spdf试图根据其输出构造一个SPDF,而无需“等待” {{ 1}}或表达式的任何其他最后部分。任何想法如何解决这个问题?

谢谢。

2 个答案:

答案 0 :(得分:4)

您应该正确地继承dataframe的子类。为了使copy-constructor方法有效,pandas描述了必须设置_constructor属性(以及其他信息)。

您可以执行以下操作:

class SPDF(DataFrame):

    @property
    def _constructor(self):
        return SPDF

如果您需要在attributes方法(如functions)中保留自定义copy-constructor(而不是diff-这些将在那里),则可以执行类似的操作以下

class SPDF(DataFrame):
    _metadata = ['prop']
    prop = 1

    @property
    def _constructor(self):
        return SPDF

注意输出是所需的:

df = SPDF(np.eye(4))
print(type(df))
[<class '__main__.SPDF'>]
new = df.diff()
print(type(new))
[<class '__main__.SPDF'>]

答案 1 :(得分:0)

如果您不想继承final EntityGraph<GeoObject> objGraph = em.createEntityGraph(GeoObject.class); objGraph.addAttributeNodes("histogram"); objGraph.addSubclassSubgraph(A.class).addAttributeNodes("pictures"); objGraph.addSubclassSubgraph(B.class).addAttributeNodes("lines"); 的子类,则可以引入另一个类似DataFrame的类,并用它包装非数据帧对象:

PendingSPDF