У меня есть фрейм данных панд с миллионами аккаунтов.У фрейма данных есть столбец с именем «eventHappens», равный 1 в периоде, в котором происходит событие.Вот пример:
import pandas as pd
account = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3]
period = [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 1, 2, 3, 4, 5, 1, 2, 3]
eventHappens = [0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0]
willHappenIn2 = [0, 1, 1, 1, -1, -1, -1, -1, -1, -1, 0, 0, 1, 1, 1, 0, 0, 0]
df = pd.DataFrame(
{'account': account ,
'period': period,
'eventHappens': eventHappens
})
print(df)
account period eventHappens
0 1 1 0
1 1 2 0
2 1 3 0
3 1 4 1
4 1 5 0
5 1 6 0
6 1 8 0
7 1 9 0
8 1 10 1
9 1 11 0
10 2 1 0
11 2 2 0
12 2 3 0
13 2 4 0
14 2 5 1
15 3 1 0
16 3 2 0
17 3 3 0
Я хочу создать новый столбец "willHappenIn2", который будет иметь все нули, кроме двух периодов до и на дату события first , которая будетзакодированы как 1 (я сохраняю -1 на случай, если позже я захочу изучить характеристики события публикации данных).Периоды после даты события должны быть закодированы как -1.Вот мой желаемый результат.Есть ли способ сделать это, не просматривая все учетные записи?
account period eventHappens willHappenIn2
0 1 1 0 0
1 1 2 0 1
2 1 3 0 1
3 1 4 1 1
4 1 5 0 -1
5 1 6 0 -1
6 1 8 0 -1
7 1 9 0 -1
8 1 10 1 -1
9 1 11 0 -1
10 2 1 0 0
11 2 2 0 0
12 2 3 0 1
13 2 4 0 1
14 2 5 1 1
15 3 1 0 0
16 3 2 0 0
17 3 3 0 0
Обновление:
Приведенный ниже ответ положил следующее решение (вывод ответа, показанный ниже, соответствует тому, что я хочу).Однако, когда я запускаю его на моей машине, результат не соответствует желаемому результату.Есть предложения?
df.loc[df.loc[df.eventHappens==1].groupby('account').eventHappens.idxmax(),'key']=1
s1=df.key.where(df.key==1).groupby(df.account).bfill(2) # using groupby with bfill get the 1 foward with limit 2
s2=(-df.key.where(df.key==1)).groupby(df.account).ffill() # adjust the key and get the back adjust to -1
s1.fillna(s2).fillna(0)
Out[110]:
0 0.0
1 -1.0
2 -1.0
3 1.0
4 -1.0
5 1.0
6 0.0
7 0.0
8 1.0
9 0.0
10 0.0
11 0.0
12 1.0
13 1.0
14 1.0
15 0.0
16 0.0
17 0.0
Обновление 2: Сработало следующее.Мне пришлось изменить метод bfill на .apply () с помощью replace () и метода «bfill».Это не так красиво, как 1-й ответ (который послужил моим руководством, спасибо!), Но он работает на моей машине.
df["willHappenIn2_step1"] = df.eventHappens.groupby(df['account']).cumsum().astype(int)
df["willHappenIn2_step2"] = df.willHappenIn2_step1.groupby(df['account']).cumsum().astype(int)
df["willHappenIn2_step3"] = df.willHappenIn2_step2
df.loc[df.willHappenIn2_step2>1,"willHappenIn2_step3"] = -1
df['Final_OutPut'] = df["willHappenIn2_step3"].groupby(df.account).apply( lambda x: x.replace(to_replace=0, method='bfill', limit = 2))
df["willHappenIn2Desired"] = willHappenIn2
print(df)