Подтвердить что ты не робот

Как вызвать pandas.rolling.apply с параметрами из нескольких столбцов?

У меня есть набор данных:

    Open     High      Low    Close        
0  132.960  133.340  132.940  133.105
1  133.110  133.255  132.710  132.755
2  132.755  132.985  132.640  132.735 
3  132.730  132.790  132.575  132.685
4  132.685  132.785  132.625  132.755

Я пытаюсь использовать функцию roll.apply для всех строк, например:

df['new_col']= df[['Open']].rolling(2).apply(AccumulativeSwingIndex(df['High'],df['Low'],df['Close']))
  • показывает ошибку

или

df['new_col']=  df[['Open', 'High', 'Low', 'Close']].rolling(2).apply(AccumulativeSwingIndex)
  • передать только параметр из столбца "Открыть"

Может кто-нибудь мне помочь?

4b9b3361

Ответ 1

Определите свой собственный roll

Мы можем создать функцию, которая принимает аргумент размера окна w и любые другие ключевые аргументы. Мы используем это для создания нового DataFrame, в котором мы будем вызывать groupby при передаче аргументов ключевого слова через kwargs.

Примечание: мне не нужно было использовать stride_tricks.as_strided, но оно лаконично и, на мой взгляд, уместно.
from numpy.lib.stride_tricks import as_strided as stride
import pandas as pd

def roll(df, w, **kwargs):
    v = df.values
    d0, d1 = v.shape
    s0, s1 = v.strides

    a = stride(v, (d0 - (w - 1), w, d1), (s0, s0, s1))

    rolled_df = pd.concat({
        row: pd.DataFrame(values, columns=df.columns)
        for row, values in zip(df.index, a)
    })

    return rolled_df.groupby(level=0, **kwargs)

roll(df, 2).mean()

       Open      High       Low    Close
0  133.0350  133.2975  132.8250  132.930
1  132.9325  133.1200  132.6750  132.745
2  132.7425  132.8875  132.6075  132.710
3  132.7075  132.7875  132.6000  132.720

Мы также можем использовать метод pandas.DataFrame.pipe для того же эффекта:

df.pipe(roll, w=2).mean()


СТАРЫЙ ОТВЕТ

Panel устарела. См. выше для обновленного ответа.

см fooobar.com/questions/456684/...

определить наш собственный roll

def roll(df, w, **kwargs):
    roll_array = np.dstack([df.values[i:i+w, :] for i in range(len(df.index) - w + 1)]).T
    panel = pd.Panel(roll_array, 
                     items=df.index[w-1:],
                     major_axis=df.columns,
                     minor_axis=pd.Index(range(w), name='roll'))
    return panel.to_frame().unstack().T.groupby(level=0, **kwargs)

вы должны быть в состоянии:

roll(df, 2).apply(your_function)

Использование mean

roll(df, 2).mean()

major      Open      High       Low    Close
1      133.0350  133.2975  132.8250  132.930
2      132.9325  133.1200  132.6750  132.745
3      132.7425  132.8875  132.6075  132.710
4      132.7075  132.7875  132.6000  132.720

f = lambda df: df.sum(1)

roll(df, 2, group_keys=False).apply(f)

   roll
1  0       532.345
   1       531.830
2  0       531.830
   1       531.115
3  0       531.115
   1       530.780
4  0       530.780
   1       530.850
dtype: float64

Ответ 2

Поскольку ваше скользящее окно не слишком велико, я думаю, что вы также можете поместить их в один и тот же кадр данных, а затем использовать функцию apply для уменьшения.

Например, с набором данных df следующим образом

            Open    High        Low     Close
Date                
2017-11-07  258.97  259.3500    258.09  258.67
2017-11-08  258.47  259.2200    258.15  259.11
2017-11-09  257.73  258.3900    256.36  258.17
2017-11-10  257.73  258.2926    257.37  258.09
2017-11-13  257.31  258.5900    257.27  258.33

Вы можете просто добавить скользящие данные в этот фрейм данных с помощью

window = 2
df1 = pd.DataFrame(index=df.index)
for i in range(window):
    df_shifted = df.shift(i).copy()
    df_shifted.columns = ["{}-{}".format(s, i) for s in df.columns]
    df1 = df1.join(df_shifted)
df1

           Open-0   High-0      Low-0   Close-0 Open-1  High-1      Low-1   Close-1
Date                                
2017-11-07  258.97  259.3500    258.09  258.67  NaN     NaN         NaN     NaN
2017-11-08  258.47  259.2200    258.15  259.11  258.97  259.3500    258.09  258.67
2017-11-09  257.73  258.3900    256.36  258.17  258.47  259.2200    258.15  259.11
2017-11-10  257.73  258.2926    257.37  258.09  257.73  258.3900    256.36  258.17
2017-11-13  257.31  258.5900    257.27  258.33  257.73  258.2926    257.37  258.09

Тогда вы можете легко подать заявку со всеми необходимыми данными

df1.apply(AccumulativeSwingIndex, axis=1)

Ответ 3

Попробуйте это для передачи нескольких столбцов для применения

df['new_column'] = df.apply(lambda x: your_function(x['High'],x['Low'],x['Close']), axis=1)