J'ai un grand dataframe tenant des utilisateurs de cartographie (index) pour compte d'éléments (colonnes):Comment vectoriser le calcul de pandas impliquant un groupement personnalisé?
users_items = pd.DataFrame(np.array([[0, 1, 1, 0], # user 0
[1, 0, 0, 0], # user 1
[5, 0, 0, 9], # user 2
[0, 3, 5, 0], # user 3
[0, 2, 2, 0], # user 4
[7, 0, 0, 1], # user 5
[3, 5, 0, 4]]), # user 6
columns=list('ABCD'))
Pour chaque utilisateur, je veux trouver tous les utilisateurs qui ont compte non nuls pour au moins la même articles et additionner leurs comptes. Donc, pour l'utilisateur 1, ce serait les utilisateurs 1, 2, 5 et 6 et la somme des comptes est égale à [16, 5, 0, 14]
. Cela peut être utilisé pour suggérer de nouveaux éléments aux utilisateurs en fonction des éléments que les utilisateurs "similaires" ont obtenus.
Cette implémentation naïve utilise une signature comme une expression régulière pour filtrer les lignes pertinentes et une boucle en boucle sur toutes les signatures:
def create_signature(request_counts):
return ''.join('x' if count else '.' for count in request_counts)
users_items['signature'] = users_items.apply(create_signature, axis=1).astype('category')
current_items = users_items.groupby('signature').sum()
similar_items = pd.DataFrame(index=current_items.index,
columns=current_items.columns)
for signature in current_items.index:
row = current_items.filter(regex=signature, axis='index').sum()
similar_items.loc[signature] = row
Le résultat est:
A B C D
signature
.xx. 0 6 8 0
x... 16 5 0 14
x..x 15 5 0 14
xx.x 3 5 0 4
Cela fonctionne bien, mais il est trop lent pour l'ensemble de données réel qui se compose de 100 000 utilisateurs et quelque 600 articles. La génération des signatures ne prend que 10 secondes, mais le bouclage de toutes les signatures (40k) prend plusieurs heures.
La vectorisation de la boucle devrait offrir une énorme amélioration des performances, mais mon expérience avec Pandas est limitée, donc je ne sais pas comment s'y prendre. Il est même possible de vectoriser ce type de calcul? Peut-être en utilisant des masques?
Pourquoi y at-il seulement 4 signatures pour l'exemple? Avez-vous besoin d'autres combinaisons comme .x ..,. Xxx, x.xx etc? Pourquoi ces 4 sont-ils choisis? – Allen
@Allen L'ensemble des signatures résulte simplement des données qui se trouvent dans la structure de données users_items. Toutes les signatures possibles ne se produiront pas. –
donc 'x ...' devrait être la somme de toutes les lignes dont il est un sous-ensemble –