Скользящие панды применяются к df, где фильтр основан на значениях в текущей строке - PullRequest
0 голосов
/ 27 декабря 2018

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

В качестве надуманного примера:

name = ['steve', 'bob', 'harry', 'jeff'] * 5
df = pd.DataFrame(
    index=pd.DatetimeIndex(start='2018-10-10', end='2018-10-29', freq='D'), 
    data={'value': [x for x in range(20)],
          'name': names
         }
)

создает простой фрейм данных, к которому я хотел бы добавить еще один столбец (result), который вычисляет количество строк * сумму значений в 'value'(или что-то - просто формула, для которой нет встроенной функции Pandas).Поэтому для приведенного выше кадра данных мне хотелось бы следующее:

            num   name  result
2018-10-10    0  steve     NaN    
2018-10-11    1    bob     NaN
2018-10-12    2  harry     NaN
2018-10-13    3   jeff     NaN
2018-10-14    4  steve       0
2018-10-15    5    bob       1
2018-10-16    6  harry       2
2018-10-17    7   jeff       3
2018-10-18    8  steve       8
2018-10-19    9    bob      12
2018-10-20   10  harry      16
2018-10-21   11   jeff      20
2018-10-22   12  steve      24
2018-10-23   13    bob      28
2018-10-24   14  harry      32
2018-10-25   15   jeff      36
2018-10-26   16  steve      40
2018-10-27   17    bob      44
2018-10-28   18  harry      48
2018-10-29   19   jeff      52

Я могу написать свою собственную функцию для этого и использовать ее в pandas.apply:

def rolling_apply(df, time, window_size=timedelta(days=10)):
    event_time = time
    event_name = df[df.index == time]['names'].iloc[0]

    return df[
        (df['names'] == event_name) & 
        (df.index < event_time) & 
        (df.index >= event_time - window_size)
    ]

df['result'] = df.apply(lambda x: rolling_apply(df, x.name)['value'].sum() * rolling_apply(df, x.name).count(), axis=1)

, но производительность возрастаетдовольно ужасно довольно быстро, как мои данные растут.pandas.rolling.apply кажется уместным, но я не могу сделать так, чтобы это соответствовало тому, что я хочу сделать.

Буду очень признателен за любые предложения или помощь!

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