Première rédaction de cet article le 14 juin 2009
Le site social Stack Overflow ayant désormais rendu publique sa base de données, il est possible de l'analyser et d'étudier les comportements des participants à ce site. Par exemple, les votes et les réponses se poursuivent-ils pendant des mois ou bien sont-ils concentrés dans les heures qui suivent la publication d'une question ?
Regardons d'abord l'évolution des votes dans le temps. Combien de temps s'écoule t-il entre un message (question ou réponse) et les votes sur ce message ?
so=> SELECT DISTINCT (votes.creation - posts.creation::date) AS interval,
so-> to_char(count(votes.id)*100.0/
so(> (SELECT count(votes.id) FROM Posts, Votes
so(> WHERE Votes.post = Posts.id), '99.99') AS
so-> percent
so-> FROM Votes, Posts
so-> WHERE Votes.post = Posts.id
so-> GROUP BY interval ORDER BY interval;
interval | percent
----------+---------
0 | 54.75
1 | 10.33
2 | 2.62
3 | 1.74
4 | 1.26
5 | 1.01
6 | .87
7 | .70
8 | .57
9 | .49
10 | .44
11 | .42
12 | .38
13 | .39
14 | .39
15 | .33
16 | .30
...
La majorité absolue des votes ont lieu le jour de publication de l'article. Dès le cinquième jour, on passe en dessous d'un pour cent des votes pour la journée. Bref, il semble que le syndrôme connu à Stack Overflow sous le nom de fastest gun in West joue à plein. N'importe quel contributeur peut le voir : si on arrête d'écrire, la réputation ne bouge plus guère, les votes tardifs étant rares.
Cela se voit très bien sur le graphique, produit par gnuplot avec ces instructions :
set xrange [:150] set format y "%.0f" plot "votes-per-day.dat" using 1:2 with lines title ""
et en extrayant les données avec psql --file
votes-per-day.sql --field-separator ' ' --tuples-only --no-align so >
votes-per-day.dat, on obtient :

Mais la traîne est tellement longue qu'elle contribue quand même. Ainsi, 27 % des votes ont lieu plus d'une semaine après l'article et 19 % des votes plus d'un mois après :
so=> SELECT count(votes.id)*100/(SELECT count(votes.id) FROM Posts, Votes
WHERE Votes.post = Posts.id) AS percent
FROM votes, posts WHERE
votes.post = posts.id AND
votes.creation >= (posts.creation + interval '7 day')::date;
percent
---------
27
(1 row)
so=> SELECT count(votes.id)*100/(SELECT count(votes.id) FROM Posts, Votes
WHERE Votes.post = Posts.id) AS percent
FROM votes, posts WHERE
votes.post = posts.id AND
votes.creation >= (posts.creation + interval '30 day')::date;
percent
---------
19
(1 row)
Graphiquement, en mettant l'axe des Y en logarithmique, on voit mieux la longue traîne. Les instructions gnuplot sont :
set xrange [:150] set logscale y set format y "%.0f" plot "votes-per-day.dat" using 1:2 with lines title ""
et le résultat est :

Et l'intervalle entre la question et une réponse acceptée (dans Stack Overflow, l'auteur d'une question peut marquer une question et une seule comme acceptée) ?
so=> SELECT DISTINCT(answers.creation::date - questions.creation::date) AS interval,
so-> to_char((count(questions.id)*100.0/(SELECT count(answers.id)
so(> FROM Posts questions, Posts answers
so(> WHERE answers.id = questions.accepted_answer AND
so(> questions.type = 1 AND
so(> answers.type = 2)), '999.9') AS percent
so-> FROM Posts questions, Posts answers
so-> WHERE answers.id = questions.accepted_answer AND questions.type = 1 AND
so-> answers.type = 2
so-> GROUP BY interval ORDER by interval;
interval | percent
----------+---------
0 | 83.9
1 | 7.3
2 | 1.5
3 | 1.0
4 | .7
5 | .5
6 | .4
7 | .4
8 | .3
...
La courbe est encore plus brutale. On pourrait résumer en disant que, si on ne répond pas le premier jour, on n'a que peu de chances d'être accepté... Mais il faut garder espoir. 4 % des réponses acceptées ont été écrites plus d'une semaine après l'article et 1 % après un mois.
so=> SELECT count(answers.id)*100/(SELECT count(answers.id)
FROM Posts questions, Posts answers
WHERE answers.id = questions.accepted_answer AND
questions.type = 1 AND
answers.type = 2) AS percent
FROM Posts questions, Posts answers
WHERE answers.id = questions.accepted_answer AND
questions.type = 1 AND answers.type = 2 AND
answers.creation > (questions.creation + interval '7 day')::date;
percent
---------
4
(1 row)
so=> SELECT count(answers.id)*100/(SELECT count(answers.id)
FROM Posts questions, Posts answers
WHERE answers.id = questions.accepted_answer AND
questions.type = 1 AND
answers.type = 2) AS percent
FROM Posts questions, Posts answers
WHERE answers.id = questions.accepted_answer AND
questions.type = 1 AND answers.type = 2 AND
answers.creation > (questions.creation + interval '30 day')::date;
percent
---------
1
(1 row)
Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)
Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)