唯物是真 @Scaled_Wurm

プログラミング(主にPython2.7)とか機械学習とか

アドベントカレンダーの参加者は毎年どれぐらい入れ替わっているのか?2016

去年Advent Calendarの参加者が1年間でどれぐらい入れ替わっているのか調べました
sucrose.hatenablog.com
せっかくなので今年も調べてみます

2016年と2015年のQiitaで公開されているアドベントカレンダーを調査の対象とします

2016年の分は466個、2015年の分は377個のアドベントカレンダーが得られました

名寄せがめんどくさかったので、上で得られたアドベントカレンダーのリストの内2016年と2015年のURLが年の部分以外一致するものを対象とします
すると179個のアドベントカレンダーが残りました

去年の著者の内どの程度の割合で今年も書いているか(以下、生存率と呼ぶ)を調べます

結果

今年の参加者が10人以下のアドベントカレンダーは除きました

生存率(おそらく死んではいない。残存率)は40%から50%ぐらいを中心に分布していて去年より高め
生存率の分布は下の図のような感じです
f:id:sucrose:20161201012040p:plain
結果の表です
参加者の生存率が高い順に並んでいます
生存率上位には企業のアドベントカレンダーや専門性の強いものが並んでいて、下位の方には利用者の多そうなものや流行りのものが並んでいる傾向があるように見えます

順位 カレンダー名 生存率 共通の参加者数 2016年の参加者数 2015年の参加者数
1 se 1.000 3 24 3
2 firstserver 1.000 10 25 10
3 opencv 0.875 7 12 8
4 allabout 0.800 12 19 15
5 fablic 0.786 11 14 14
6 hamee 0.778 14 20 18
7 nijibox 0.714 15 22 21
8 crowdworks 0.700 14 25 20
9 istyle 0.692 9 23 13
10 basicinc 0.692 9 16 13
11 access 0.688 11 17 16
12 speee 0.667 12 23 18
13 salesforce-app-cloud 0.667 10 16 15
14 gumi 0.632 12 21 19
15 dlang 0.625 10 18 16
16 klab 0.609 14 25 23
17 freee 0.600 15 24 25
18 eeic 0.591 13 25 22
19 cybird 0.583 14 22 24
20 pepabo 0.579 11 24 19
21 kintone 0.560 14 22 25
22 ue4 0.520 13 25 25
23 livesense_1 0.520 13 25 25
24 gaiax 0.520 13 25 25
25 wacul 0.500 7 14 14
26 vim 0.500 12 25 24
27 mynet 0.500 9 25 18
28 lang_dev 0.500 5 14 10
29 gastah 0.500 7 11 14
30 dwango 0.480 12 25 25
31 appresso 0.478 11 24 23
32 erlang 0.471 8 12 17
33 qt 0.467 7 15 15
34 sakura 0.455 10 23 22
35 goodpatch 0.455 10 18 22
36 dots_girls 0.450 9 22 20
37 siv3d 0.444 8 18 18
38 netopscoding 0.444 8 16 18
39 m3 0.444 8 14 18
40 heroku 0.444 8 11 18
41 pixiv 0.440 11 22 25
42 oculus-rift 0.440 11 25 25
43 mixi 0.440 11 20 25
44 future 0.440 11 23 25
45 clojure 0.440 11 24 25
46 webgl 0.435 10 12 23
47 ouch-hack 0.435 10 25 23
48 conoha 0.435 10 25 23
49 r-rstudio 0.417 10 25 24
50 tech-camp 0.409 9 24 22
51 postgresql 0.400 10 23 25
52 linux 0.400 8 24 20
53 julialang 0.400 6 11 15
54 http2 0.400 6 13 15
55 haskell 0.400 10 24 25
56 mruby 0.389 7 14 18
57 productmanager 0.375 6 18 16
58 sansan 0.368 7 15 19
59 unity 0.360 9 25 25
60 ruby 0.360 9 22 25
61 javaee 0.360 9 12 25
62 go 0.360 9 25 25
63 ipu 0.353 6 13 17
64 shell-script 0.350 7 15 20
65 gcp 0.348 8 25 23
66 csharp 0.348 8 25 23
67 no-girlfriend 0.333 4 25 12
68 kubernetes 0.333 1 25 3
69 drupal 0.333 7 11 21
70 azure 0.320 8 25 25
71 python 0.292 7 25 24
72 xamarin 0.286 6 25 21
73 vue 0.286 4 25 14
74 symfony 0.286 6 11 21
75 recruitlifestyle 0.280 7 25 25
76 nodejs 0.280 7 25 25
77 java 0.280 7 23 25
78 swift 0.261 6 25 23
79 crawler 0.261 6 25 23
80 php 0.250 6 21 24
81 ios 0.250 6 25 24
82 communication 0.250 4 15 16
83 bluemix 0.250 5 23 20
84 livesense_2 0.240 6 24 25
85 foss4g 0.240 6 14 25
86 civictech 0.238 5 16 21
87 scala 0.227 5 25 22
88 cakephp3 0.227 5 12 22
89 math 0.211 4 16 19
90 android 0.208 5 25 24
91 slack 0.200 3 25 15
92 swift2 0.190 4 24 21
93 pronama-chan 0.176 3 12 17
94 gsacademy 0.176 3 15 17
95 go2 0.160 4 25 25
96 dwango2 0.160 4 25 25
97 javascript 0.130 3 17 23
98 go3 0.125 3 24 24
99 git 0.120 3 25 25
100 emacs 0.091 2 11 22
101 ansible 0.087 2 11 23
102 unity2 0.083 2 22 24
103 docker 0.083 2 24 24
104 rust-lang 0.071 1 24 14
105 chainer 0.050 1 20 20
106 electron 0.042 1 17 24
107 tensorflow 0.000 0 24 1
108 react-native 0.000 0 12 1
109 laravel 0.000 0 20 3
110 blockchain 0.000 0 21 3

ソースコード

pyqueryを使ってるので入ってなかったらpip install pyqueryとかで入れてください(他にもnumpyやmatplotlibなども使っています

カレンダー数と、上の結果(はてな記法の表形式)を出力するようになっています

# -*- coding: utf-8 -*-

import pyquery
import time

def getCalendarList(year, page):
    calendar_list = pyquery.PyQuery(url='http://qiita.com/advent-calendar/{}/calendars?page={}'.format(year, page))
    title = set()
    for elm in calendar_list.find('.adventCalendarList_calendarTitle > a'):
        a = pyquery.PyQuery(elm)
        href = a.attr('href')
        title.add(href[22:])
    return title

def getAuthors(year, name):
    calendar = pyquery.PyQuery(url='http://qiita.com/advent-calendar/{}/{}'.format(year, name))
    author = set()
    for elm in calendar.find('.adventCalendarCalendar_author a'):
        a = pyquery.PyQuery(elm)
        text = a.text()
        author.add(text)
    return author

if __name__ == '__main__':
    title2015 = set()
    for i in range(1, 20):
        title2015 |= getCalendarList(2015, i)
        time.sleep(1)
    title2016 = set()
    for i in range(1, 25):
        title2016 |= getCalendarList(2016, i)
        time.sleep(1)

    print '2016: {}, 2015: {}, Intersection: {}'.format(len(title2016), len(title2015), len(title2016 & title2015))

    result = []
    for name in title2016 & title2015:
        author2016 = getAuthors(2016, name)
        time.sleep(1)
        if len(author2016) <= 10:
            continue
        author2015 = getAuthors(2015, name)
        time.sleep(1)
        result.append((float(len(author2016 & author2015)) / len(author2015), name, len(author2016), len(author2015), len(author2016 & author2015)))
    result.sort(reverse=True)
    print u'|*順位|*カレンダー名|*生存率|*共通の参加者数|*2016年の参加者数|*2015年の参加者数|'.encode('utf-8')
    for i, (score, name, num2016, num2015, num_intersect) in enumerate(result, 1):
        print '|{0}|<a href="http://qiita.com/advent-calendar/2016/{1}">{1}</a>|{2:.3f}|{3}|{4}|{5}|'.format(i, name, score, num_intersect, num2016, num2015)


from pylab import *
import numpy as np
score = np.array(map(lambda x:x[0], result))
name = np.array(map(lambda x:x[1], result))

hist(score, bins=np.arange(0, 1.1, 0.1), histtype='stepfilled')
prop = matplotlib.font_manager.FontProperties(fname=r'C:\Windows\Fonts\meiryo.ttc', size=12)
xlabel(u'生存率', fontproperties=prop)
ylabel(u'カレンダー数', fontproperties=prop)
show()