Могу ли я динамически выбирать метод, применяемый к объекту pandas Resampler?

Я пытаюсь создать функцию, которая выполняет повторную выборку данных временных рядов в pandas. Я хотел бы иметь возможность указать тип агрегации, который происходит в зависимости от того, какой тип данных я отправляю (т.е. для некоторых данных подходит сумма каждого бина, а для других требуется среднее значение, так далее.). Например такие данные:

import pandas as pd
import numpy as np

dr = pd.date_range('01-01-2020', '01-03-2020', freq='1H')
df = pd.DataFrame(np.random.rand(len(dr)), index=dr)

У меня могла бы быть такая функция:

def process(df, freq='3H', method='sum'):
    r = df.resample(freq)
    if method == 'sum':
        r = r.sum()
    elif method == 'mean':
        r = r.mean()
    #...
    #more options
    #...
    return r

Для небольшого количества методов агрегации это нормально, но кажется утомительным, если я хочу выбрать из все возможные варианты.

Я надеялся использовать getattr для реализации что-то вроде этого post (в разделе Приведение в действие: обобщение вызовов методов). Однако я не могу найти способ сделать это:

def process2(df, freq='3H', method='sum'):
    r = df.resample(freq)
    foo = getattr(r, method)
    return r.foo()

#fails with:
#AttributeError: 'DatetimeIndexResampler' object has no attribute 'foo'

def process3(df, freq='3H', method='sum'):
    r = df.resample(freq)
    foo = getattr(r, method)
    return foo(r)

#fails with:
#TypeError: __init__() missing 1 required positional argument: 'obj'

Я понимаю, почему process2 терпит неудачу (вызов r.foo() ищет метод foo() из r, а не переменную foo). Но я не думаю, что понимаю, почему process3 терпит неудачу.

Я знаю, что другим подходом будет передача функций параметру method, а затем apply этих функций r. Я склоняюсь к тому, что это будет менее эффективно? И это по-прежнему не позволяет мне напрямую обращаться к встроенным методам Resample.

Есть ли рабочий, более краткий способ добиться этого? Спасибо!


person Tom    schedule 12.08.2020    source источник
comment
Попробуйте .resample().apply(method)   -  person RichieV    schedule 13.08.2020
comment
@RichieV Спасибо! Я почему-то пропустил это, просматривая документацию. Если вы ответите, я приму.   -  person Tom    schedule 13.08.2020
comment
Сначала попробуйте и дайте мне знать, если это сработает, я не знаю, может ли method быть строкой или это должна быть ссылка на фактический метод.   -  person RichieV    schedule 13.08.2020
comment
Да, это работает, и это есть в документах для apply. Насколько я могу судить, r.apply('sum') совпадает с r.sum(). По времени тестирования они кажутся эквивалентными   -  person Tom    schedule 13.08.2020


Ответы (1)


Попробуйте .resample().apply(method)

Но если вы не планируете выполнять дополнительные вычисления внутри функции, вероятно, будет проще просто жестко запрограммировать эту строку.

person RichieV    schedule 12.08.2020