Кодирование событий, которые будут происходить в течение n периодов для логистической регрессии.В пандах - PullRequest
0 голосов
/ 11 октября 2018

У меня есть фрейм данных панд с миллионами аккаунтов.У фрейма данных есть столбец с именем «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)

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Сработало следующее.Мне пришлось изменить метод 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)
0 голосов
/ 11 октября 2018

Нам нужно использовать фильтр idxmax после, чтобы создать новый key, поскольку два 1 в одной группе не приведут к изменению выхода, поэтому мы просто получаем index первого значения, показанного как 1

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[219]: 
0     0.0
1     1.0
2     1.0
3     1.0
4    -1.0
5    -1.0
6    -1.0
7    -1.0
8    -1.0
9    -1.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
Name: key, dtype: float64
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...