Можно ли использовать векторизацию для условного подсчета строк в кадре данных Pandas? - PullRequest
0 голосов
/ 24 апреля 2018

У меня есть Pandas Dataframe с данными о звонках.Каждый звонок имеет уникальный идентификатор, и каждый клиент имеет идентификатор (но может иметь несколько вызовов).Третий столбец дает день.Для каждого клиента я хочу рассчитать максимальное количество вызовов, совершенных за 7 дней.

Я использовал следующий код для подсчета количества вызовов в течение 7 дней после вызова в каждой строке:

df['ContactsIN7Days'] = df.apply(lambda row: len(df[(df['PersonID']==row['PersonID']) & (abs(df['Day'] - row['Day']) <=7)]), axis=1)

Вывод:

CallID  Day PersonID    ContactsIN7Days
6       2   3           2
3       14  2           2
1       8   1           1
5       1   3           2
2       12  2           2
7       100 3           1

Это работает, однако будет применяться к большому набору данных.Был бы способ сделать это более эффективным.Через векторизацию?

1 Ответ

0 голосов
/ 24 апреля 2018

IIUC это запутанное, но я думаю эффективное решение вашей проблемы. Обратите внимание, что в результате порядок вашего фрейма данных изменяется, а столбец Day изменяется на d-тип временной шкалы:

Начиная с вашего фрейма данных df:

   CallID  Day  PersonID
0       6    2         3
1       3   14         2
2       1    8         1
3       5    1         3
4       2   12         2
5       7  100         3

Начните с изменения Day до серии timedelta:

df['Day'] = pd.to_timedelta(df['Day'], unit='d')

Затем используйте pd.merge_asof, чтобы объединить ваш фрейм данных с количеством вызовов каждого человека в течение 7 дней. Чтобы получить это, используйте groupby с pd.Grouper с периодичностью 7 дней:

new_df = (pd.merge_asof(df.sort_values(['Day']),
                        df.sort_values(['Day'])
                        .groupby([pd.Grouper(key='Day', freq='7d'), 'PersonID'])
                        .size()
                        .to_frame('ContactsIN7Days')
                        .reset_index(),
                        left_on='Day', right_on='Day',
                        left_by='PersonID', right_by='PersonID',
                        direction='nearest'))

Ваш результат new_df будет выглядеть так:

   CallID      Day  PersonID  ContactsIN7Days
0       5   1 days         3                2
1       6   2 days         3                2
2       1   8 days         1                1
3       2  12 days         2                2
4       3  14 days         2                2
5       7 100 days         3                1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...