2014-01-09 2 views
6

Я хотел бы использовать функцию pandas.rolling_apply для применения моей собственной пользовательской функции на основе катящегося окна.Пользовательская функция Python с использованием функции roll_apply для pandas

но моя функция требует двух аргументов, а также имеет два выхода. Это возможно?

Ниже приведен минимальный воспроизводимый пример ...

import pandas as pd 
import numpy as np 
import random 
tmp = pd.DataFrame(np.random.randn(2000,2)/10000, 
        index=pd.date_range('2001-01-01',periods=2000), 
        columns=['A','B']) 

def gm(df,p): 
    v =(((df+1).cumprod())-1)*p 
    return v.iloc[-1] 

# an example output when subsetting for just 2001 
gm(tmp['2001'],5) 


# the aim is to do it on a rolling basis over a 50 day window 
# whilst also getting both outputs and also allows me to add in the parameter p=5 
# or any other number I want p to be... 
pd.rolling_apply(tmp,50,gm) 

что приводит к ошибке ... поскольку г принимает два аргумента ...

любая помощь будет принята с благодарностью ...

EDIT

После комментария Джеффа я прогрессировал, но я до сих пор борется с двумя или более Colum n, поэтому, если вместо этого я создаю новую функцию (ниже), которая вместо двух последних чисел (не связанных с предыдущим вычислением) возвращает вместо двух последних строк v, я получаю ошибку TypeError: only length-1 arrays can be converted to Python scalars. Эта функция работает, если

def gm2(df,p): 
    df = pd.DataFrame(df) 
    v =(((df+1).cumprod())-1)*p 
    return np.random.rand(2) 

pd.rolling_apply(tmp,50,lambda x: gm2(x,5)).tail(20) 

Эта функция работает, если 2 изменяется на 1 ...

ответ

12

rolling_apply проходит Numpy массивы к прикладной функции (в-момент), на 0,14 он должен пройти кадр , Вопрос here

Так переопределите свою функцию для работы с массивом numpy. (Вы можете, конечно, построить DataFrame внутри здесь, но ваши имена индекса/столбца не будут одинаковыми).

In [9]: def gm(df,p): 
    ...:  v = ((np.cumprod(df+1))-1)*p 
    ...:  return v[-1] 
    ...: 

Если вы хотите использовать больше функций панд в пользовательской функции, сделайте это (обратите внимание, что indicies о вызывающем кадре не прошли ATM).

def gm(arr,p): 
    df = DataFrame(arr) 
    v =(((df+1).cumprod())-1)*p 
    return v.iloc[-1] 

Пасс его через лямбда

In [11]: pd.rolling_apply(tmp,50,lambda x: gm(x,5)).tail(20) 
Out[11]: 
        A   B 
2006-06-04 0.004207 -0.002112 
2006-06-05 0.003880 -0.001598 
2006-06-06 0.003809 -0.002228 
2006-06-07 0.002840 -0.003938 
2006-06-08 0.002855 -0.004921 
2006-06-09 0.002450 -0.004614 
2006-06-10 0.001809 -0.004409 
2006-06-11 0.001445 -0.005959 
2006-06-12 0.001297 -0.006831 
2006-06-13 0.000869 -0.007878 
2006-06-14 0.000359 -0.008102 
2006-06-15 -0.000885 -0.007996 
2006-06-16 -0.001838 -0.008230 
2006-06-17 -0.003036 -0.008658 
2006-06-18 -0.002280 -0.008552 
2006-06-19 -0.001398 -0.007831 
2006-06-20 -0.000648 -0.007828 
2006-06-21 -0.000799 -0.007616 
2006-06-22 -0.001096 -0.006740 
2006-06-23 -0.001160 -0.006004 

[20 rows x 2 columns] 
+0

как вы «переопределить вашу функцию, чтобы работать на Numpy массиве.»? –

+1

вы можете использовать только функции numpy (а не функции pandas); или вы можете сделать '' DataFrame (df) '', чтобы сделать его фреймом – Jeff

+0

Означает ли это, что в пользовательской функции я могу запускать только функции numpy и функции pandas? –

Смежные вопросы