Pandas: использование скользящих окон с пользовательскими функциями

У меня есть кадр данных, из которого я оцениваю 10-летние скользящие средние различных видов с синтаксисом скользящего стиля старого стиля:

`pandas.rolling_mean(df['x'], 10)`, 
`pandas.rolling_median(df['x'], 10)`

а также

`pandas.rolling_apply(df['x'],10, hodgesLehmanMean)`,

где hodgesLehman означает функцию, которую я написал (см. ниже).

def hodgesLehmanMean(x):
    #Computes the Hodges-Lehman mean = median { [x_i + x+j]/2 }. 
    #Robust to 29% outliers, with high (95% efficiency) in the gaussian case

    N = len(x)
    return 0.5 * numpy.median(x[i] + x[j] for i in range(N) for j in range(i+1,N))
`

Теперь, когда старые функции прокатки устарели, я пытаюсь переписать свой код в новом стиле series.rolling(), то есть:

`df['x'].rolling(window=10).mean()`, 
`df['x'].rolling(window=10).median()`
 and 
`df['x'].rolling(window=10).hodgesLehmanMean()`.

Первые два (среднее и медиана) работают как часы. Третий (hodgesLehmanMean) не работает - поднимает AttributeError: 'Rolling' object has no attribute 'hodgesLehmanMean

Как я могу заставить свою функцию работать с новым синтаксисом series.rolling?


person Thomas Philips    schedule 02.11.2017    source источник


Ответы (1)


Вы можете позвонить Rolling.apply/agg:

df['x'].rolling(window=10).agg(hodgesLehmanMean)

Также обратите внимание, что в вашей функции вы хотите передать список в np.median, а не генератор:

def hodgesLehmanMean(x): 
    return 0.5 * np.median([x[i] + x[j] 
                           for i in range(len(x)) 
                           for j in range(i+1,len(x))])

Для более быстрой реализации hodgesLehmanMean посмотрите ответ unutbu на один из ваших старых вопросов здесь.

person cs95    schedule 02.11.2017
comment
Спасибо за указатель - сработало как шарм. Я не знал об agg и сразу же заработал, следуя вашим указаниям. На самом деле я использую более быструю реализацию hodgesLehmanMean в unutbu, которая была опубликована в ответ на мой более ранний вопрос, но намеренно не публиковала ее, на случай, если это вызовет путаницу в отношении характера моей проблемы. Спасибо еще раз! Томас Филипс - person Thomas Philips; 03.11.2017
comment
@ThomasPhilips Если ответ помог, проголосуйте за него и примите ответ. Спасибо. - person cs95; 03.11.2017
comment
Действительно, так оно и было, и я принял ответ и проголосовал за него. Спасибо еще раз. - person Thomas Philips; 05.11.2017