Применить функцию к MultiIndex DataFrame от Groupby - PullRequest
1 голос
/ 16 февраля 2020

Я хочу сгруппировать ('Ticker') этот мультииндексный Dataframe, а затем применить функцию, которая возвращает Series для каждого тикера, и добавить результат в новый столбец на df.

def Indicator(dataf):

    df = dataf.copy()
    df['TR1'] = df.High.sub(df.Low)
    df['TR2'] = abs(df.High.sub(df.Close.shift(1)))
    df['TR3'] = abs(df.Low.sub(df.Close.shift(1)))
    df['TR'] = df[['TR1', 'TR2', 'TR3']].max(axis=1)
    df['TR_mean'] = df['TR'].resample('M').mean().shift(1).resample('D').fillna('bfill')
    df['Vol_mean'] = df['Volume'].resample('M').mean().shift(1).resample('D').fillna('bfill')
    indicator = (df.TR.div(df.TR_mean)).div(df.Volume.div(df.Vol_mean))

    return indicator

Я пытаюсь что-то вроде этого:

tickers.groupby('Ticker').apply(Indicator)

Но я получаю эту ошибку: допустимо только с DatetimeIndex, TimedeltaIndex или PeriodIndex, но получил экземпляр 'MultiIndex'

Dataframe:

                        Close           High         Low               Open         Volume
Date        Ticker                  
2010-01-04  AAPL        6048.299805    6048.299805  5974.430176 5975.520020 1.043444e+08
            GOOG        1132.989990    1133.869995  1116.560059 1116.560059 3.991400e+09
            TSM         10654.79003    10694.49023  10608.13948 10609.33984 1.044000e+05
2010-01-05  AAPL        6031.859863    6058.020020  6015.669922 6043.939941 1.175721e+08
            GOOG        1132.989990    1133.869995  1116.560059 1116.560059 3.991400e+09
            TSM         10654.79003    10694.49023  10608.13948 10609.33984 1.044000e+05

1 Ответ

1 голос
/ 16 февраля 2020

Чтобы исправить эту ошибку, вам нужно просто добавить следующую строку в функцию Indicator после операции copy:

df.index = df.index.get_level_values(0)

Проблема действительно заключается в том, что вы передать функцию MultiIndex вместо индекса DateTime методу resample в функции (которая является функцией для работы с временными рядами). То, что делает дополнительная строка, в основном заменяет MultiIndex только частью индекса DateTime. Это приводит к следующему:

>>> df_orig
                          Close          High           Low          Open        Volume
Date       Ticker
2010-01-04 AAPL     6048.299805   6048.299805   5974.430176   5975.520020  1.043444e+08
           GOOGL    1132.989990   1133.869995   1116.560059   1116.560059  3.991400e+09
           TSM     10654.790030  10694.490230  10608.139480  10609.339840  1.044000e+05
2010-01-05 AAPL     6031.859863   6058.020020   6015.669922   6043.939941  1.175721e+08
           GOOGL    1132.989990   1133.869995   1116.560059   1116.560059  3.991400e+09
           TSM     10654.790030  10694.490230  10608.139480  10609.339840  1.044000e+05

>>> df_orig.info()
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 6 entries, (2010-01-04 00:00:00, AAPL) to (2010-01-05 00:00:00, TSM)
Data columns (total 5 columns):
Close     6 non-null float64
High      6 non-null float64
Low       6 non-null float64
Open      6 non-null float64
Volume    6 non-null float64
dtypes: float64(5)
memory usage: 410.0+ bytes

>>> df_orig.groupby("Ticker").apply(Indicator)
Date    2010-01-04  2010-01-05
Ticker
AAPL           NaN         NaN
GOOGL          NaN         NaN
TSM            NaN         NaN

Конечно, вы также можете удалить столбец Ticker до применения групповой заявки, например:

ticker_idx = df_orig.index.get_level_values(1)
df_orig.reset_index(1, drop=True).groupby(ticker_idx).apply(Indicator)

Таким образом, вы не ' Мне не нужно добавлять эту дополнительную строку в функцию.

Кроме того, я получаю кучу NaN в результате операции groupby-apply, но, глядя на код вашей функции, я предполагаю, что это из-за к тому, что функция ожидала больше данных, чем 2 дня. Дайте мне знать, если это правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...