Я хотел бы создать DataFrame, возможно, разреженный, который измеряет корреляции между пользователями. Здесь мое определение корреляции между user_1
и user_2
- это количество раз, когда они оба выполнили один и тот же action
в один и тот же день.
Я попытаюсь объяснить себя лучше на примере. Предположим, у меня есть следующий Dataframe:
date action user
6 2019-05-05 b user_3
9 2019-05-05 b user_2
1 2019-05-06 b user_2
5 2019-05-06 a user_1
0 2019-05-07 b user_3
7 2019-05-07 a user_2
8 2019-05-07 a user_1
2 2019-05-08 c user_2
4 2019-05-08 c user_1
3 2019-05-09 c user_3
, который можно сгенерировать с помощью этого фрагмента:
import numpy as np
import pandas as pd
np.random.seed(12)
users = np.random.choice(['user_1', 'user_2', 'user_3'], size=10)
actions = np.random.choice(['a', 'b', 'c'], size=10)
date = np.random.choice(pd.date_range(start='2019-05-05', end='2019-05-10', freq='D'), size=10)
df = pd.DataFrame(dict(date=date, action=actions, user=users))
df.date = pd.to_datetime(df.date)
df = df.sort_values('date')
Корреляция между user_1
и user_2
равна 2
, так как они оба выполнено действие a
в день 07
и действие c
в день 08
. Корреляция между user_2
и user_3
равна 1
, поскольку они выполнили действие b
в день 05
. Все остальное NaN
. Они выводят DataFrame, который я ищу:
user_1 user_2 user_3
user_1 NaN NaN NaN
user_2 2.0 NaN NaN
user_3 NaN 1.0 NaN
Мой неэффективный способ создания этого DataFrame следующий:
from itertools import combinations
df_result = pd.DataFrame(columns=['user_1', 'user_2', 'user_3'],
index=['user_1', 'user_2', 'user_3'], dtype=np.float64)
for index, group in df.groupby(['date', 'action']):
for x, y in combinations(list(group.user.values), 2):
if np.isnan(df_result.loc[x,y]):
df_result.loc[x, y] = 1
else:
df_result.loc[x, y] = df_result.loc[x, y] + 1
Проблема с этим подходом заключается в способ замедления в моем случае использования.