唯物是真 @Scaled_Wurm

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

Advent Calendarの参加者は毎年どれぐらい入れ替わっているのか?

Machine Learning Advent Calendarの参加者を去年の参加者と比べると入れ替わりが激しいんだなーと思ったので他のも調べてみました

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

2014の分は210個、2013年の分は82個(満員になった分しか公開されていない?)のアドベントカレンダーが得られました

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

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

結果

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

中央値を見ると生存率はおよそ30%ぐらいでした
生存率の分布は下の図のような感じです
f:id:sucrose:20141214145712p:plain

結果の表です
参加者の生存率が高い順に並んでいます
上の方は専門性が高そうなものが並んでいて、下の方には利用者の多そうなものが並んでいる傾向があるように見えます

1位のD言語はさすがですね(?)
Machine Learning Advent Calendarは34個中30位なので、最初に思った通り入れ替わりが激しい方でした

順位 カレンダー名 生存率 共通の参加者数 2014年の参加者数 2013年の参加者数
1 dlang 0.615 8 16 13
2 postgresql 0.611 11 21 18
3 groonga 0.600 6 11 10
4 delphi 0.600 6 14 10
5 laravel 0.545 6 22 11
6 clojure 0.500 12 24 24
7 gastah 0.474 9 11 19
8 haskell 0.458 11 25 24
9 xamarin 0.400 2 21 5
10 go 0.400 10 25 25
11 azure 0.400 10 24 25
12 lisp 0.360 9 17 25
13 ios 0.360 9 25 25
14 perl 0.333 6 23 18
15 scala 0.304 7 25 23
16 civictech 0.304 7 16 23
17 haxe 0.300 3 11 10
18 unity 0.292 7 24 24
19 zsh 0.286 4 13 14
20 php 0.280 7 25 25
21 fluentd 0.250 6 16 24
22 cocos2d-x 0.250 4 18 16
23 android 0.240 6 25 25
24 mongodb 0.235 4 14 17
25 minor-language 0.231 3 13 13
26 git 0.208 5 22 24
27 ruby 0.200 5 25 25
28 ansible 0.200 3 23 15
29 one-minute 0.160 4 24 25
30 machinelearning 0.160 4 25 25
31 javascript 0.160 4 24 25
32 python 0.000 0 24 8
33 linux 0.000 0 11 4
34 aws 0.000 0 25 10

ソースコード

pyqueryを使ってるので入ってなかったらpip install pyqueryとかで入れてください

前にpyqueryを使ったのでそのまま使いましたが、最近読んだ以下の記事によるといろいろ便利そうなライブラリがあるみたいですね

Pythonでクローリング・スクレイピングに使えるライブラリいろいろ - orangain flavor

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

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

import pyquery
import time

def getCalendarList(year):
    calendar_list = pyquery.PyQuery(url='http://qiita.com/advent-calendar/{}'.format(year))
    title = set()
    for elm in calendar_list.find('.adventCalendar_calendarList_calendarTitle a:nth-child(2)'):
        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('.adventCalendar_calendar_author a'):
        a = pyquery.PyQuery(elm)
        text = a.text()
        author.add(text)
    return author

if __name__ == '__main__':
    title2014 = getCalendarList(2014)
    title2013 = getCalendarList(2013)

    print '2014: {}, 2013: {}, Intersection: {}'.format(len(title2014), len(title2013), len(title2014 & title2013))

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


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=6, 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()