Pandas和Pandas一起上课。管道()

2024-09-28 19:30:55 发布

您现在位置:Python中文网/ 问答频道 /正文

@pd.api.extensions.register_dataframe_accessor("data_cleaner")
class DataCleaner:

    def __init__(self, pandas_obj):
        self._obj = pandas_obj

    def multiply(self, col):
        self._obj[col] = self._obj[col] * self._obj[col]
        return self._obj 
    
    def square(self, col):
        self._obj[col] = self._obj[col]**2
        return self._obj 
    
    def add_strings(self, col):
        self._obj[col] = self._obj[col] + self._obj[col]
        return self._obj 

    def process_all(self):
        self._obj.pipe(
            self.multiply(col='A'),
            self.square(col='B')
            self.add_strings(col='C')
        )
    

class DataProcessor(DataCleaner):

    data = [
        [1, 1.5, "AABB"],
        [2, 2.5, "BBCC"],
        [3, 3.5, "CCDD"],
        [4, 4.5, "DDEE"],
        [5, 5.5, "EEFF"],
        [6, 6.5, "FFGG"],
    ]

    def __init__(self):
        self.df = pd.DataFrame(data=DataProcessor.data, columns=['A', 'B', 'C'])

    def get_data(self):
        return self.df
    
    def clean_the_df(self, obj):
        obj = obj.data_cleaner.multiply(col='A')
        obj = obj.data_cleaner.square(col='B')
        obj = obj.data_cleaner.add_strings(col='C')
        return obj
    
    def process_all(self, obj):
        obj = obj.data_cleaner.process_all()


if __name__ == '__main__':
    

    data = DataProcessor().get_data()
    
    # this works
    print(DataProcessor().clean_the_df(data))
    
    # this does not work
    print(DataProcessor().process_all(data))

我想将pandas.pipe()函数与数据帧访问器一起使用,以将方法链接在一起。在DataCleaner类中,我有一个方法process_all,该方法包含类内的其他清理方法。我想把它们链接在一起,用多种方法一次性处理数据帧

将此链接方法保留在DataCleaner类中会很好,因此我所要做的就是从另一个类或文件调用它一次,例如process_allDataProcessor

这样,我就不必逐个写出每个方法来处理数据帧,例如在DataProcessor.clean_the_df()

问题是process_all在抱怨:TypeError: 'DataFrame' object is not callable

所以我的问题是,如何使用pandas数据帧访问器self.obj.pipe()将一个函数中的多个清理方法链接在一起,以便我可以从另一个类调用该函数,并使用多个方法一次性处理数据帧

带有process_all的所需输出:

    A      B         C
0   1   2.25  AABBAABB
1   4   6.25  BBCCBBCC
2   9  12.25  CCDDCCDD
3  16  20.25  DDEEDDEE
4  25  30.25  EEFFEEFF
5  36  42.25  FFGGFFGG

Tags: 数据方法selfobjpandasdfdatareturn
1条回答
网友
1楼 · 发布于 2024-09-28 19:30:55

这里的问题是.pipe需要一个接受数据帧、序列或GroupBy对象的函数。关于这一点,文件非常清楚:https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pipe.html。除此之外,DataCleaner.process_all函数没有正确实现.pipe。为了链接多个函数,预期语法为:

>>>(df.pipe(h)
...    .pipe(g, arg1=a)
...    .pipe(func, arg2=b, arg3=c)
... ) 

这相当于

>>>func(g(h(df), arg1=a), arg2=b, arg3=c) 

为了将数据帧访问器与.pipe相结合,您需要在DataCleaner类中定义静态方法,这些方法将数据帧和列作为参数。以下是修复您的问题的示例:

@pd.api.extensions.register_dataframe_accessor("data_cleaner")
class DataCleaner:
    def __init__(self, pandas_obj):
        self._obj = pandas_obj

    @staticmethod
    def multiply(df, col):
        df[col] = df[col] * df[col]
        return df 
    
    @staticmethod
    def square(df, col):
        df[col] = df[col]**2
        return df
    
    @staticmethod
    def add_strings(df, col):
        df[col] = df[col] + df[col]
        return df 

    def process_all(self):
        self._obj = (self._obj.pipe(self.multiply, col='A') 
                              .pipe(self.square, col='B')
                              .pipe(self.add_strings, col='C'))
        return self._obj 

class DataProcessor(DataCleaner):
    data = [
        [1, 1.5, "AABB"],
        [2, 2.5, "BBCC"],
        [3, 3.5, "CCDD"],
        [4, 4.5, "DDEE"],
        [5, 5.5, "EEFF"],
        [6, 6.5, "FFGG"],
    ]
    def __init__(self):
        self.df = pd.DataFrame(data=DataProcessor.data, columns=['A', 'B', 'C'])

    def get_data(self):
        return self.df
    
    def clean_the_df(self, obj):
        obj = obj.data_cleaner.multiply(obj, col='A') # modified to use static method
        obj = obj.data_cleaner.square(obj, col='B')
        obj = obj.data_cleaner.add_strings(obj, col='C')
        return obj
    
    def process_all(self, obj):
        obj = obj.data_cleaner.process_all()
        return obj

使用此代码,运行此命令将产生:

>>>data = data = DataProcessor().get_data()
>>>print(DataProcessor().process_all(data))
    A      B         C
0   1   2.25  AABBAABB
1   4   6.25  BBCCBBCC
2   9  12.25  CCDDCCDD
3  16  20.25  DDEEDDEE
4  25  30.25  EEFFEEFF
5  36  42.25  FFGGFFGG

相关问题 更多 >