Bon, j'ai compris
1
d[:,0] signifie "la colonne 0" de l'array bidimensionnel d.
d[8,:] est la "8ième ligne" de l'array bidimensionnel d.
L' array d[0,:] est un iterable que map() peut donc recevoir en argument.
map(int,d[:,0]) fait des éléments de l'array des entiers.
Ce qui me perturbait, c'est qu'on applique array() au produit de map() alors que d paraissait être un array dès le départ.
Mais c'est parce que map() renvoie toujours une liste , donc pour retrouver un array, on est obligé d'appliquer array() sur le résultat de map(). L'array obtenu est une ligne puisque les éléments de map(int,d[:,0]) sont des entiers et non pas des sous-listes.
d[8,:] peut se représenter aussi par d[8] parce que 'éventuels ':' après le 8 sont sous-entendus. Pour une colonne la notation d[:,x] est obligée.
d[:,0] signifie donc "colonne 0 d'un array bidimensionnel" , mais s'il s'agit d'un array de dimension 3, la signification devient alors "les lignes 0 de tous les tableaux bidimensionnels qui sont en premier indice", ou "tous les tableaux bidimensionnels d'indice antépénultiéme égal à 0" pour un array de dimension 4, etc.
Cependant il est certain que d est un array bidimensionnel parce que si ce n'était pas le cas la fonction int() dans le map() ne pourrait pas s'appliquer à des éléments qui seraient des lignes ou de nature pire encore, donc non transformables en entier.
2
z = N.zeros_like(user)+1 crée un tableau rempli de zéros de même shape que le tableau user, c'est à dire en l'occurence un tableau-ligne , puis ajoute 1 ---> tableau-ligne rempli de 1: [1 1 1 1 1 .....]
3
user==userlist[5] est équivalent à
[user[0]==userlist[5] user[1]==userlist[5] user[2]==userlist[5] user[3]==userlist[5] user[4]==userlist[5] user[5]==userlist[5] user[6]==userlist[5]....]
Donc cond2 = user==userlist[5] sera un tableau rempli de False sauf aux positions où la valeur du tableau sera celle de la position 5 de la liste. Finalement c'est un moyen de trouver toutes les positions où se trouve un élément donné.
Par exemple si
userlist = [3 , 89 , 3 , 50 , 20 , 3 , 7]
et user = [3 89 3 50 20 3 7]
alors user==userlist[5] sera [ True False True False False True False]
C'est la même chose pour
cond1=(folder==folderlist[i])*z
sauf que le fait de multiplier par z transforme les True en 1 et le False en 0, ce qui permet un décompte.
user et folder sont issus de d,
donc ces tableaux-lignes ont la même longueur.
Je prends donc la même longueur pour un exemple avec
folderlist = ['8','1','22','13','46','52','22']
et folder = ['8' '1' '22' '13' '46' '52' '22']
on a (folder==folderlist[2])*z = [0 0 1 0 0 0 1]
4
Je pense que d est un array bidimensionnel du genre
1 2 3 4 5 6 7
| [[ 3 8]
[89 1]
[ 3 22]
[50 13]
[20 46]
[ 3 52]
[ 7 22]] |
qui collationne les couples (utilisateur,numero de folder) chaque fois qu'un utilisateur consulte un folder. Dans la colonne 0, les numéros d'utilisateurs peuvent apparaître plusieurs fois, et de même pour les numéros de dossiers dans la colonne 1.
Pour éviter d'itérer sur des séquences contenant des éléments répétés, je pense que la fonction uniq() a pour mission de produire une liste sans doublons à partir d'un tableau qui en contient.
Je ne sais pas comment elle est codée. Perso j'utilise
li_sans_doublons = list(set(li))
quand la liste li n'est pas trop grande. Je n'ai pas testé la vitesse, mais à mon avis ça doit être foufroyant.
5
Bon, il semble donc que le code passe en revue les folders (itération sur i) et que
pour chaque folder i:
- il fait la somme des 1 qui apparraissent dans
(folder==folderlist[i])*z * (user==userlist[j])
c'est le nombre de fois que l'utilisateur j a utilisé le folder i
- il ajoute ce nombre à activity_count_user
Il n'y a donc dans activity_count_user d'un folder i que des nombres de consulations de ce dossier i, sans liaison avec les identités des utilisateurs mais ce nombre de consultation est identique au nombre d'utilisateurs.
Et finalement activity_count_user_folder liste les listes d'activités de tous les folders.
Bon, tout ceci, c'est évidemment si je ne me trompe pas sur la nature de d.
On en est réduit à reconstituer les questions, quand il n'y a pas assez de renseignements qui sont donnés.
Mais je donne les réponses aussi ! 6 - Pour ce qui est d'optimiser:
- j'ai testé la fonction sum() et je me suis aperçu que
[False False True False False False True].sum() donne 2.
Donc ce n'est pas la peine de se casser la tête avec z = N.zeros_like(user)+1 :
cond1 peut s'écrire simplement cond1=(folder==folderlist[i])
Les décomptes se feront sur des tableaux de booléens.
- ensuite,
1 2
| for j in range(0,l_u):
cond2 = (user==userlist[j]) |
c'est lourd. Remplacer par
1 2
| for ut in userlist:
cond2 = (user==ut) |
- puis,
1 2 3 4
| activity_count_user = []
for ut in userlist:
cond2 = (user==ut)
activity_count_user.append((cond1*cond2).sum()) |
évite de mettre à chaque fois une valeur cond1*cond2 dans une variable cm
- et hop, encore une fois et plus de variable cond2 :
1 2 3
| activity_count_user = []
for ut in userlist:
activity_count_user.append((cond1*(user==ut)).sum()) |
- et on peut finalement mettre ça sous forme de list comprehension:
activity_count_user = [ (cond1*(user==ut)).sum() for ut in userlist ]
- on fait la même chose pour
1 2 3
| for i in range(0,l_f):
print i, "out of ", len(folderlist)
cond1=(folder==folderlist[i])*z |
on remplace par
1 2 3
| for fo in folderlist:
print i, "out of ", len(folderlist)
cond1=(folder==fo) |
- et finalement encoe, pour éviter une affectation de valeur à une variable cond1, on fait
1 2 3 4 5
| activity_count_user_folder = []
for i,fo in enumerate(folderlist):
print i, "out of ", l_f
activity_count_user = [((folder==fo)*(user==ut)).sum() for ut in userlist ]
activity_count_user_folder.append(activity_count_user) |
- si on aime la concision et qu'on est prêt à se passer de l'impression de i, "out of ", l_f
on finit par deux list comprehension imbriquées:
1 2 3 4
|
#
activity_count_user_folder = [ [ ((folder==fo)*(user==ut)).sum() for ut in userlist ] for fo in folderlist ]
# |
- et miracle, si on aime la concision (un peu alambiquée quand même) ET qu'on tienne à son print i, "out of ", l_f , Python assure toujours 
:
1 2 3 4 5 6 7 8
| def fprint(i):
if i//100==0:
print i, "out of ", l_f
activity_count_user_folder = []
[ (activity_count_user_folder.append( [ ((folder==fo)*(user==ut)).sum() for ut in userlist ] ) , fprint(i) ) for i,fo in enumerate(folderlist) ]
print activity_count_user_folder
# |
En sommant directement sur des booléens, en itérant directement dans les listes et non plus les indices, en éliminant des affectations de variables, et en utilisant des listes comprehension, ça devrait s'accélérer notablement.
J'aimerais bien avoir un retour, vu le mal que je me suis donné pour comprendre la question.
#
Partager