У меня есть фрейм данных 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
кажется уместным, но я не могу сделать так, чтобы это соответствовало тому, что я хочу сделать.
Буду очень признателен за любые предложения или помощь!