Панды Группируют функцию применения внутри класса

#python #pandas

Вопрос:

Меня беспокоит использование groupby.apply функции в классе. Вот код:

 import pandas as pd
import numpy as np
from datetime import datetime, timedelta, date

class Calculator:
    def __init__(self):
        self.df = pd.DataFrame({'date_time': [date(2021,6,1), date(2021,6,2), date(2021,6,3), date(2021,6,4), date(2021,6,1), date(2021,6,2), date(2021,6,3), date(2021,6,4)],
                    'ticker':   ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
                    'close':   [5, 4, 2, 3, 10, 12, 11, 12]})


    def expected_calculation(self):
        self.df['weight'] = self.df['close'].values / self.df['close'].sum()
        self.df['pct_change'] = self.df['close'].values.pct_change()


    def job(self):
        self.df = self.df.groupby(['date_time', 'ticker']).apply(self.expected_calculation)


if __name__ == '__main__':
    testing = Calculator()
    testing.job()
 

Я попытался запустить приведенный выше код, но он возвращает мне ошибку TypeError: expected_calculation() takes 1 positional argument but 2 were given . Это необходимо использовать groupby , потому что я хочу провести расчет по каждому подмножеству (т. Е. по одному набору данных для тикера). Я понимаю, что это связано с apply функцией, но я не могу найти выход.

Не могли бы вы помочь мне решить эту проблему? Большое спасибо!

Ответ №1:

Это связано с тем,что при использовании apply он передает значения строк в качестве аргументов функции.Поэтому expected_calculation функция ожидает значения строк в качестве параметра. Другое дело-следовать лучшим практикам при работе с классами.Ваша expeted_calculation функция не имеет ничего общего с экземплярами class.so его лучше использовать staticmethod . Попробуйте это решение

 class Calculator:
    def __init__(self):
        self.df = pd.DataFrame({'date_time': [date(2021,6,1), date(2021,6,2), date(2021,6,3), date(2021,6,4), date(2021,6,1), date(2021,6,2), date(2021,6,3), date(2021,6,4)],
                    'ticker':   ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
                    'close':   [5, 4, 2, 3, 10, 12, 11, 12]})

    @staticmethod
    def expected_calculation(x):
        x['weight'] = x['close'].values / x['close'].sum()
        x['pct_change'] = x['close'].pct_change()
        return x


    def job(self):
        self.df = self.df.groupby(['date_time', 'ticker']).apply(self.expected_calculation)