Jouons avec l'API des membres

Qui sera le plus original ?

a marqué ce sujet comme résolu.

Pour le coup, j'ai essayé d'analyser un peu l'activité des membres grace à la date de dernière visite des membres. On en arrive aux conclusions suivantes :

  • Si on considère qu'un membre actif est un membre qui s'est connecté sur le site pendant les 4 dernières semaines, alors sur 1815 membres ayant un compte sur zds (activé), 672 membres (~37%) sont actifs en ce moment
  • Si on considère qu'un membre actif est un membre qui s'est connecté sur le site cette semaine, alors sur 1815 membres ayant un compte sur zds (activé), 312 membres (~17%) sont actifs en ce moment

Maintenant voici quelques schémas qui nous montre ce qu'on gagne (Inscriptions) et ce qu'on perd (Les membres qui ne se reconnectent plus) sur le site par mois et par semaine.

Si on considère qu'un membre actif est un membre qui s'est connecté sur le site cette semaine

Cette hypothèse est fausse. Il ne faut pas confondre la date de dernière connexion (auth_user.last_login) qui est mise à jour à chaque connexion (clic sur le bouton "se connecter) et la date de dernière visite (member_profile.last_visit) qui est mise à jour à chaque visite, par tranches de 10 minutes.

Par exemple, c'est très possible que je sois compté comme inactif avec ton système "sur la semaine".

Voici ce que donnent les requêtes en prod :

1
2
3
4
select count(*) from auth_user where last_login > DATE_ADD(NOW(), INTERVAL -7 DAY);
-- 352
select count(*) from member_profile where last_visit > DATE_ADD(NOW(), INTERVAL -7 DAY);
-- 479

Soit quand même presque 40% de différence.

Avec un délais d'un mois (30 jours) par contre, les chiffres sont pratiquement identiques (731 pour 734). On peut donc en déduire que beaucoup de gens sont en connexion automatique, mais finissent par passer sur la mire de connexion au moins une fois par mois.

En utilisation quotidienne (24 heures), ça devient dantesque comme différence : 88 contre 288.

PS : Je ne sais pas ce que donne exactement l'API, mais vu les chiffres il s'agit de la date de dernière connexion - qui n'a donc aucun sens ou presque pour les valeurs < 1 mois.

Ah oui, ils sont jolis tes graphes Kje. Du coup j’ai un peu modifié mon script pour avoir un rendu similaire et pouvoir regarder de près ce pic étrange au deux tiers d’octobre 2014. Ça donne ceci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# -*- coding: utf-8 -*-


from __future__ import (absolute_import, division,
                        print_function)
import urllib2
import json
from pprint import pprint
from datetime import datetime
import matplotlib.dates
import matplotlib.pyplot as plt
import numpy as np
from time import sleep
import math
import sys

# date_list = []
# url = 'http://zestedesavoir.com/api/membres/?page=1&page_size=100'

# while(url):
    # print(url)
    # try:
        # response = urllib2.urlopen(url)
    # except urllib2.HTTPError, e:
        # print(e)
        # print(u'arrête de spammer le ZdS')
        # break
    # data = json.loads(response.read())
    # for user in data['results']:
        # strdate = user['date_joined']
        # date = datetime.strptime(strdate, '%Y-%m-%dT%H:%M:%S')
        # numdate = matplotlib.dates.date2num(date)
        # date_list.append(numdate)
    # np.savetxt('datelist.txt', date_list)
    # url = data['next']
    # sleep(5) # laisse le serveur respirer
    

date_list = np.loadtxt('datelist.txt')
date_list.sort()
nb_days = math.floor(date_list[-1]-date_list[0])
    
fig = plt.figure()
ax1 = fig.add_subplot(111)

ax1.step(date_list , range(len(date_list)), 'b-')
ax1.set_ylabel(u'nombre de membres')
for tl in ax1.get_yticklabels():
    tl.set_color('b')

ax2 = ax1.twinx()
bins = np.linspace(math.floor(date_list[0]), math.floor(date_list[-1]), nb_days)
ax2.hist(date_list, bins=bins, alpha=0.7, facecolor='g', edgecolor='none')
ax2.set_ylabel(u'nombres de membres/jours',)
for tl in ax2.get_yticklabels():
    tl.set_color('g')

locs = matplotlib.dates.AutoDateLocator()
ax2.xaxis.set_major_locator(locs)
ax2.xaxis.set_major_formatter(matplotlib.dates.AutoDateFormatter(locs))
fig.suptitle(u'Évolution du nombres de membres')
ax2.grid(True)
fig.autofmt_xdate()
plt.show()

Je ne vous donne pas l’image parce que c’est sensiblement la même chose qu’au dessus. Le truc c’est que du coup je peux zoomer.

Pour la petite histoire le pic c’était le 17 octobre, il y a eu 15 membres qui se sont inscrits en 30 minutes (entre 8h34 et 9h04). Bon, il est probable que ce soit une coïncidence fortuite ici, 15 personnes c’est rien du tout.

Mais imaginez qu’on ait un vrai pic, on pourrait essayer de recouper ça avec des activités sur les réseaux sociaux la veille et en déduire des choses sur les membres en question (puisque on sait qui ils sont). Vous trouvez ça malsain ? Moi aussi, et dites-vous qu’on ne joue ici qu’avec des minuscules données publiques, imaginez ce qu’on pourrait faire avec beaucoup de données privées.

Alors pour ZdS, pas de soucis, on a le code source, on sait ce qui se passe. On ne peut pas en dire autant d’autres service Web bien connu…

+0 -0

Le pic du 17 octobre, c'est pas du tout une coïncidence : c'est juste un type qui s'est amusé à faire des tests en prod…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
test2
@78test|◉
&amp;
select * from toto;
testtest
testtesttestr
111111111111111111111111111111
a
dsfgdsg
X
p◉@_*a5
&#34;a
SELECT *;

Cette hypothèse est fausse. Il ne faut pas confondre la date de dernière connexion (auth_user.last_login) qui est mise à jour à chaque connexion (clic sur le bouton "se connecter) et la date de dernière visite (member_profile.last_visit) qui est mise à jour à chaque visite, par tranches de 10 minutes.

SpaceFox

L'API revoit bien la date de dernière visite, et non la date de dernière connexion. La reflexion est basée essentiellement la dessus justement. Le delta que tu as c'est peut être parce que tu as oublié de virer les membres qui n'ont jamais activé leur compte.

Ce qui pourrait être plus intéressant, c'est d'essayer de cerner les membres qui se sont investis un tout petit peu, et de voir si leurs nombres augmentent au diminuent (en comparant avec la date de dernière activité).

Par exemple, une métrique, certainement imparfaite, pourrait être les membres qui ont personnalisé leur avatar, puisque l'utilisation du forum est à ce jour la seule raison de s'inscrire il me semble. Il existe probablement d'autres métriques plus adaptées, mais ça permettrait d'éviter les comptes créés pour des tests, ou ceux créés mais jamais utilisés.

Comme je doutai de la date de dernière visite, à raison, j'ai regardé le reste des données pour faire un profil type du membre. Alors :

  • $93.3\%$ des membres sont actifs
  • Seulement $9.6\%$ ont coché l'option "Recevez un courriel lorsque vous recevez une réponse à un message privé"
  • Seulement $1.33\%$ ont coché l'option "Afficher mon adresse courriel publiquement"
  • $36.2\%$ des membres ont mit un avatar
  • $7.33\%$ des membres ont mit une bio
  • $13.4\%$ des membres ont mit une signature
  • $10.3\%$ des membres ont renseigné leur site web

Maintenant, quelques graphes, sur les inscriptions (j'ai prit cette fois TOUTES les données) :

Jour de la semaine d'inscription

Quand on prend toutes les inscriptions, on se rend compte que la majorité des membres se sont inscrit en semaine, et plutôt en début de semaine.

Heure d'inscription

Pour l'heure, pas de surprise, c'est entre 9h et minuit que les membres s'inscrivent.

Enfin, dernier point, les pseudos :

Longueur des pseudos des membres

Nous remarquons que la majorité des membres ont un pseudo à $[5-8]$ caractères de long. Le max étant à 6, la longueur médiane étant à 7.

Donc résumons, notre membre typique à les caractéristique suivantes :

  • Il a activé son compte,
  • il ne souhaite pas recevoir de mail quand il a reçu un message privé et que celle-ci soit affiché publiquement,
  • il n'a pas d'avatar, ni de bio, ni de signature ni de site web renseigné,
  • il s'est inscrit un mardi vers 11h,
  • son pseudo fait 6-7 caractère de long.
+3 -0

L'API revoit bien la date de dernière visite, et non la date de dernière connexion.

Vérification faite, l'API doit renvoyer la date de dernière connexion, parce que mes chiffres restent cohérents même en excluant les utilisateurs qui n'ont jamais activé leur compte :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
select count(*)
from auth_user u
where u.last_login > DATE_ADD(NOW(), INTERVAL -7 DAY)
  and u.is_active = 1;

select count(*)
from member_profile p
inner join auth_user u on u.id = p.user_id
where p.last_visit > DATE_ADD(NOW(), INTERVAL -7 DAY)
  and u.is_active = 1;
Intervalle Dernière… Tous utilisateurs Actifs uniquement
24 HOUR Connexion 88 84
24 HOUR Visite 288 2901
7 DAY Connexion 352 346
7 DAY Visite 479 478
30 DAY Connexion 731 716
30 DAY Visite 734 732

En résumé, si l'API est vraiment sensée renvoyer la date de dernière visite… il y a un bug à corriger :)

PS : c'est cohérent avec le fait qu'on a seulement 6.7% de membres non activés (131/1952).


  1. Des nouveaux membres sont revenus entre les deux requêtes, ce qui fait que curieusement le nombre avec les actif est supérieur au nombre sans. Il faudrait relancer les premières requêtes, mais j'ai autre chose à faire. 

En tout cas, l'API renvoi bien le champ last_visit d'après le code.

Remarque que tes requêtes calcule par intervalle de 7 jours à partir de la date d'aujourd'hui, alors que moi je travaille par numéro de semaine, donc on ne peut pas avoir exactement les mêmes chiffres.

Hmmm du coup je veux bien les détails de ce que tu as fait, ça me paraît louche comme résultat…

Je pense vraiment que ce genre de stats sont plus pertinentes via la base de données que via l'API, ne serait-ce que parce que la base de données évite ce genre de problèmes.

Hmmm du coup je veux bien les détails de ce que tu as fait, ça me paraît louche comme résultat…

SpaceFox

Là en l’occurrence je calcule la semaine de chaque date de dernière visite et de chaque date d'inscription pour chaque membre. Ensuite, par semaine, je compte les membres dont leur date de dernière visite est dans ladite semaine et les membres dont leur date d'inscription est dans ladite semaine. Ce qui donne les schémas postés.

Je ne saurais dire si c'est normal la proportion des membres perdus (il faudrait le comparer aux résultats d'un autre site du même genre), en plus du fait qu'un membre peut très bien lire des tutoriels sans se connecter. Mais ce que ça montre c'est que depuis fin décembre, la proportion des membres qui ne reviennent plus (au sens, qui n'utilisent plus leur compte) évolue plus vite que la proportion des membres qui s'inscrivent.

Dis, firm1, comment tu calcules le nombre de membre "perdus". Sont-ils comptés 2 fois (i.e si je suis perdu en janvier et que je ne suis pas revenu en février, suis-je encore compté comme perdu ou bien tu as un algo qui m'a exclus parce que j'avais déjà été compté précédemment?)

atragis : dans mon calcul les perdus ne sont perdus qu'une seule fois. Si ta dernière visite date du mois d'octobre 2014 par exemple, ça veut dire que tu as été perdu en octobre 2014 et que donc tu n'es pas revenu depuis. On pourrait affiner ce calcul pour savoir quel est le profil des membres perdus, pourquoi se sont-ils inscrit, etc. Mais les données de l'API a elles toutes seule ne sont pas suffisantes.

Par contre dans l'histogramme cumulé, je cumule donc les perdus pour visualiser leur évolutions. On remarquera que mon histogramme s'arrête à Mois-1 (janvier dans notre cas) car on ne peut pas vraiment dire que les membres qui ne se sont pas encore connectés depuis février sont déjà perdus.

Pour rebondir sur ce que dit firm1, voici le graphe des sessions actives au sens Django du terme depuis l'ouverture du site.

Une session active au sens Django du terme, c'est :

  • Une session présente sur le serveur
  • Qui est affectée à un utilisateur connecté.
  • Qui n'est pas désactivée. Une session est désactivée :
    • Soit par une déconnexion manuelle
    • Soit quand elle a plus de 2 semaines d'âge (valeur par défaut non écrasée sur Zeste de Savoir)

Donc, on mesure ici quelque chose de proche de ce que firm1 voulait mesurer (les utilisateurs actifs, = qui ont visité le site connectés dans les 2 dernières semaines), mais de différent dans le sens où un utilisateur qui se connecte depuis plusieurs endroits va se retrouver avec plusieurs sessions :

Attention à l'origine qui démarre à 800 (0.8k) et non 0 !

On voit bien qu'après le pic dû au lancement du site et au creux général d'octobre, on oscille assez aléatoirement entre 1200 et 1400 sessions. Le nombre d'utilisateurs actifs (puisqu'il s'agit bien de cela) est donc à peu près stable, même si ce serait mieux s'il était plus stable, voire augmentait.

Il faut se méfier de ce genre de courbe. L'intervalle de temps est beaucoup trop courte pour conclure quelque chose ici. Tu as cette impression lié aux dernières valeurs mais la courbe peut très bien redescendre ensuite jusqu'à 1200 sans que ça sorte de la variance qu'on observe depuis décembre.

+2 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte