はじめに

eto_tori_kakizome.png

2017年もあっという間に終わりが近づいてきました。
昨年もこの時期に

なんて記事を書いていたのですが、個人的に面白かったので今年も似たようなことを色々やってみます。
なお、この記事で用いている各種データは 2017年12月12日あたり のデータであり、リアルタイムなものでないことにご留意ください。

やること

kaisya_snack_man.png

昨年は Qiita User Ranking というサイトでContributionの上位を確認することができたのですが、2017年3月頃から更新が止まってしまいましたので、今回は自前でデータを集めました。

  • ユーザ別Contributionランキング
  • ユーザ別記事数ランキング
  • ユーザ別フォロワーランキング
  • 記事別いいねランキング
  • その他分析いろいろ

それでは、いってみます。

前準備

hakui_nimotsu_hakobu_man.png

分析をするにあたり、当然データを集めなければなりません。
まとまっているものではないため、シェル芸を駆使してちまちま集めました。
ちょうど Software Design(2018年1月号) の特集「使えるシェルスクリプトの書き方」の5章で「シェルスクリプトでWebスクレイピング」がありましたが、やっているイメージは同じです。
特集でも同様に触れていますが、一気に集めるとQiita側に迷惑がかかるので適宜sleepさせつつ5日間くらいかけてゆるーっと集めています。
興味本位であっても複数人がやるとさらに負荷がかかってしまうので、一旦現時点でスクリプトの公開は控えておきます。

収集のしやすさと分析することを念頭に、ユーザごとに情報が1行にまとまるようにしつつ、

[ユーザ名],[記事数],[コントリビューション数],[フォロワー数],[ストック数1位記事:いいね数],[ストック数2位記事:いいね数],...,[ストック数5位記事:いいね数]

を集めています。内容的には ユーザページ で取れるものですね。
例えば以下のような感じになります。

qiita_data.csv
$ grep t_nakayama0714 qiita_data.csv
t_nakayama0714,33,6721,167,[エンジニアなら知っておきたい、絵で見てわかるセキュア通信の基本](https://qiita.com/t_nakayama0714/items/83ac0b12ced9e7083927):2585,[不思議の国のSE用語](https://qiita.com/t_nakayama0714/items/478a8ed3a9ae143ad854):1507,[Ansibleをはじめる人に。](https://qiita.com/t_nakayama0714/items/fe55ee56d6446f67113c):606,[NoSQLについて 勉強する。](https://qiita.com/t_nakayama0714/items/0ff7644666f0122cfba1):448,[無料で整える趣味チームの開発環境](https://qiita.com/t_nakayama0714/items/c0eb5e298524c127bccd):294

総量はどれくらいになったかというと、

ユーザ総数のカウント
$ wc -l qiita_data.csv
200902 qiita_data.csv

ということで、現在Qiitaユーザは登録数ベースで 20万 を超えているようです...!

ユーザ別分析

pop_kojinno_kansoudesu.png

まずはユーザ別に分析をしてみます。

ユーザ別Contributionランキング

昨年もやったようなものです。
ユーザごとのランキングの他、記事数や平均いいね数、Contributionに占めるいいね1位記事の割合を出してみたいと思います。
今回は元データがまとまっているので去年ほどここでは苦労しません。

ユーザ別Contributionランキング
$ cat qiita_data.csv | sort -k 3nr,3 -t , | awk -F"," 'BEGIN{OFS="|"}{TOP=substr($5,index($5,"):")+2) ; TOP_ITEM=substr($5,0,index($5,"):")) ; print "|"NR"|@"$1,$3,$2,$3/$2,TOP,TOP/$3*100"%",TOP_ITEM"|"}' | head -n 10

2017年12月12日付近のTOP100は以下のようになりました。
せっかく昨年のデータがあるので、そことの差分も出してみました。つい最近1位の座が @jnchito さんに渡っていますね...!

ランク 前年比 ユーザ名 総Contribution 前年比 記事数 平均いいね Top数 Top占有率 Top記事
1 +1 @jnchito 33833 +6880 179 189.011 2704 7.9922% モデルやメソッドに名前を付けるときは英語の品詞に気をつけよう
2 -1 @hirokidaichi 33183 +2193 33 1005.55 5041 15.1915% ペアプログラミングして気がついた新人プログラマの成長を阻害 する悪習
3 +1 @icoxfog417 27896 +8969 147 189.769 2891 10.3635% Pythonを書き始める前に見るべきTips
4 -1 @suin 22531 +2411 697 32.3257 4328 19.2091% 【まとめ】これ知らないプログラマって損してんなって思う汎用的なツール 100超
5 0 @shu223 19843 +2752 176 112.744 1361 6.8588% ディープラーニングの有名ライブラリ5種を最短距離で試す半日コース(TensorFlow, Chainer, Caffe, DeepDream, 画風変換)
6 0 @KeithYokoma 18243 +1506 142 128.472 4707 25.8017% うまくメソッド名を付けるための参考情報
7 +3 @mizchi 17591 +2490 201 87.5174 1881 10.693% 春からはじめるモダンJavaScript / ES2015
8 -1 @yuku_t 17160 +1026 195 88 1465 8.5373% 中規模Web開発のためのMVC分割とレイヤアーキテクチャ
9 +4 @mpyw 17052 +3092 257 66.3502 2055 12.0514% PHPでデータベースに接続するときのまとめ
10 -2 @kenju 16864 +1421 120 140.533 2381 14.1188% 中上級者になるためのJavaScript【知識編】
11 +1 @opengl-8080 16789 +2628 238 70.542 1228 7.31431% AngularJS使い方メモ
12 -1 @awakia 15827 +1185 152 104.125 1598 10.0967% 開発フロー研修 @ Wantedly
13 +1 @mono0926 14837 +1548 94 157.84 1372 9.24715% ローディング時のズルい進捗表示
14 +3 @b4b4r07 13127 +1475 57 230.298 1575 11.9982% さいつよのターミナル環境を構築しよう
15 0 @muran001 13078 +766 34 384.647 4542 34.7301% Gitでやらかした時に使える19個の奥義
16 +4 @cognitom 13045 +1556 95 137.316 1841 14.1127% そろそろ真面目に、HTMLで帳票を描く話をしようか
17 -1 @haminiku 13013 +869 71 183.282 2951 22.6773% 2016年 独りで新規WEBサービスを開発・運用した際の知見
18 +1 @edo_m18 12634 +1084 372 33.9624 1145 9.06285% WebのUIテスト自動化 - Seleniumを使ってみる
19 +12 @koher 12002 +3462 63 190.508 1422 11.848% null安全でない言語は、もはやレガシー言語だ
20 -2 @appwatcher 11830 +247 60 197.167 2070 17.4979% iOSでこんなアプリ,こんな機能を作りたかったらこれを見ろ!作り たいアプリに対応するクラス、フレームワーク、ライブラリのまとめ!
21 +1 @kazunori279 11636 +1374 41 283.805 1312 11.2754% Cloud Vision APIの凄さを伝えるべくRasPi botとビデオを作った話
22 -1 @susieyy 11544 +697 50 230.88 1941 16.8139% Swiftで作られたイケてるUIライブラリたち
23 +2 @zaru 11498 +2105 109 105.486 1598 13.8981% Webフロントエンド表示速度、最速化手法まとめ
24 -1 @yimajo 11055 +808 143 77.3077 737 6.66667% iOS実機のSSL通信をプロキシによって傍受したり改ざんする方法
25 +12 @kawasima 10196 +2489 78 130.718 1026 10.0628% GitHub English Challenge Cheat Sheet
26 +9 @hshimo 10021 +1946 307 32.6417 2578 25.726% プログラマが独立・起業する時によくするミスと対策 まとめ
27 +6 @kenmatsu4 9990 +1475 65 153.692 1653 16.5465% 【機械学習】ディープラーニング フレームワークChainerを試しながら解説し てみる。
28 0 @ynakayama 9889 +952 189 52.3228 713 7.21003% scikit-learn から学ぶ機械学習の手法の概要
29 -5 @hkusu 9771 +528 208 46.976 964 9.86593% [WEB開発] 私的な最近のおすすめサービス/ツール 14選 ~2014年版~
30 +4 @takeharu 9697 +1395 18 538.722 1481 15.2728% JavaScriptの「this」は「4種類」??
31 -5 @uasi 9671 +671 117 82.6581 2102 21.7351% 英語のコメントや issue で頻出する略語の意味 (FYI, AFAIK, ...)
32 -5 @kidach1 9602 +612 84 114.31 1314 13.6846% Nginx導入時やること
33 -3 @joker1007 9539 +773 105 90.8476 1089 11.4163% てめえらのRailsはオブジェクト指向じゃねえ!まずはCallbackクラ ス、Validatorクラスを活用しろ!
34 -2 @tukiyo3 9301 +774 1555 5.98135 432 4.64466% たくさんあるオープンソースライセンスのそれぞれの特徴のまとめ
35 +1 @tadsan 9191 +1396 167 55.0359 1965 21.3796% ライセンスの選択を恐れる必要はありません
36 +2 @usagimaru 8581 +1003 173 49.6012 1036 12.0732% iOS ヒューマンインターフェースの原則
37 +2 @kawaz 8243 +680 146 56.4589 2032 24.6512% 最強のSSH踏み台設定
38 +4 @okappy 8098 +880 28 289.214 5637 69.6098% 非デザイナーエンジニアが一人でWebサービスを作るときに便利なツール32選
39 +17 @tonkotsuboy_com 8027 +2239 113 71.0354 895 11.1499% 2016年新機能! GitHubのmasterブランチをWebページとして公開する手順
40 +3 @gaogao_9 7985 +901 13 614.231 4169 52.2104% 旧石器時代のJavaScriptを書いてる各位に告ぐ、現代的なJavaScript超入門 Section1 ~すぐにでも現代っぽく出来るワンポイントまとめ~
41 +3 @zembutsu 7923 +1053 87 91.069 1299 16.3953% Docker 入門ハンズオン資料
42 +9 @Quramy 7772 +1421 85 91.4353 1978 25.4503% Electronでアプリケーションを作ってみよう
43 -3 @sion_cojp 7730 +387 41 188.537 3568 46.1578% インフラエンジニアとしてよく使うコマンド集
44 +3 @vvakame 7634 +986 48 159.042 1296 16.9767% Gradle入門
45 -4 @syui 7535 +217 212 35.5425 1364 18.1022% MacBookAirで使っている便利ツール
46 @rana_kualu 7484 192 38.9792 1880 25.1203% 2017年のフロントエンドエンジニアならこの程度は知ってて当然だよ な?
47 -1 @Qiita 7385 +642 4 1846.25 5937 80.3927% Markdown記法 チートシート
48 +17 @y_hokkey 7290 +2282 60 121.5 1584 21.7284% Dockerで即実行できる、社内・自宅向けオープンソースWebアプリ
49 +49 @Hironsan 7286 +3278 46 158.391 996 13.6701% 機械学習を使って作る対話システム
50 -1 @tbpgr 7240 +854 728 9.94505 937 12.942% Markdown記法 サンプル集
51 -6 @kaiinui 7191 +382 47 153 2466 34.2929% 最近の行儀のよい JavaScript の書き方
52 -4 @Jxck_ 6992 +412 62 112.774 1137 16.2614% DELETE_FLAG を付ける前に確認したいこと。
53 +5 @tatesuke 6873 +1602 40 171.825 2179 31.7038% You Don't Need jQuery
54 -2 @yuya_presto 6811 +487 38 179.237 783 11.4961% Gitコンフリクト解消ガイド(git mergetoolの使い方)
55 @t_nakayama0714 6721 33 203.667 2585 38.4615% エンジニアなら知っておきたい、絵で見てわかるセキュア通信の基本
56 +4 @tag1216 6711 +1441 90 74.5667 2781 41.4394% インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識
57 -2 @n0bisuke 6583 +781 266 24.7481 710 10.7854% 3行のソースコードを入れるだけで機械学習できると噂のindicoをNode.jsで使って機械学習入門してみる
58 -5 @gogotanaka 6571 +442 57 115.281 3368 51.2555% ネイティブと働いて分かった英語コミットメッセージの頻出動詞10つ
59 -9 @armorik83 6527 +161 110 59.3364 1340 20.5301% AngularJSモダンプラクティス
60 +2 @amay077 6452 +1365 254 25.4016 464 7.19157% Xamarin(ザマリン) とはなんぞや
61 +6 @shibukawa 6259 +1332 100 62.59 871 13.916% オブジェクト指向と20年戦ってわかったこと
62 -3 @jacksuzuki 6118 +850 5 1223.6 6106 99.8039% ロシアの天才ハッカーによる【新人エンジニアサバイバルガイド】
63 -9 @yaotti 6110 +215 151 40.4636 1268 20.7529% gitでありがちな問題の解決方法まとめ
64 +20 @howdy39 5979 +1603 43 139.047 1238 20.7058% フロントエンドにテストを導入
65 +14 @kazukichi 5939 +1455 34 174.676 2284 38.4577% エンジニアで稼ぐために大切な19のコト
66 -9 @r7kamura 5859 +278 56 104.625 690 11.7768% RailsでAPIをつくるときのエラー処理
67 +1 @magicant 5708 +837 36 158.556 2128 37.281% クラスの命名のアンチパターン
68 -4 @daxanya1 5618 +576 30 187.267 4514 80.3489% 数学を避けてきた社会人プログラマが機械学習の勉強を始める際の最短経路
69 -3 @koba04 5516 +546 38 145.158 770 13.9594% 私のJavaScript情報の集め方
70 +4 @mochizukikotaro 5454 +873 240 22.725 1044 19.1419% 初心者がAWSでミスって不正利用されて$6,000請求、泣きそうになったお話。
71 +1 @nekoneko-wanwan 5452 +768 56 97.3571 1477 27.091% はじめてajaxを使うときに知りたかったこと
72 -11 @voluntas 5451 +351 107 50.9439 1053 19.3176% docker コマンド チートシート
73 -4 @koogawa 5447 +589 63 86.4603 1217 22.3426% iPhoneアプリ申請やAppleの審査に関するメモ
74 +6 @disc99 5416 +945 24 225.667 1939 35.8013% Javaを使うなら知っておきたい技術、フレームワーク、ライブラリ、ツールまとめ
75 -4 @hidekuro 5402 +671 81 66.6914 2158 39.9482% VagrantとDockerについて名前しか知らなかったので試した
76 -13 @hnakamur 5368 +315 187 28.7059 530 9.87332% ちょっとしたHTMLはGitHub Gistに置いてbl.ocks.orgで表示するのが お手軽です
77 +13 @tenntenn 5353 +1123 71 75.3944 1968 36.7644% Go言語の初心者が見ると幸せになれる場所 #golang
78 +9 @hik0107 5322 +1017 22 241.909 859 16.1405% Pythonでデータ分析するのに必要なツールのまとめ
79 +7 @ukiuni@github 5267 +981 60 87.7833 1969 37.3837% JavaScriptを読んでて「なにこれ!?」と思うけれど調べられな い記法8選。
80 -5 @chuck0523 5178 +611 44 117.682 1540 29.7412% フロントエンドエンジニアが暇なときにやると良いかもしれないこと
81 +7 @pugiemonn 5144 +910 265 19.4113 937 18.2154% こんなHTMLとCSSのコーディング規約で書きたい
82 @shizuma 5126 102 50.2549 657 12.817% ターミナル 作業効率化 tips集
83 @colorrabbit 5064 253 20.0158 624 12.3223% 覚えておきたい Vim コマンド 備忘録
84 @TakahikoKawasaki 4974 20 248.7 1287 25.8745% 一番分かりやすい OAuth の説明
85 @inuscript 4971 111 44.7838 419 8.42889% 【古い記事】Babelにおける import / export
86 -13 @okmttdhr 4971 +307 70 71.0143 1932 38.8654% ここ数年前から2015/5までのモダンフロントエンドを総まとめしてみ た
87 +2 @ryounagaoka 4959 +729 47 105.511 1968 39.6854% もう逃げない。HTMLのviewportをちゃんと理解する
88 -18 @puriketu99 4928 +137 183 26.929 875 17.7557% 機械学習クソ素人の俺がプロダクトをリリースするまでの2ヶ月で覚 えたこと
89 -6 @Hiraku 4872 +502 125 38.976 1240 25.4516% WebAPIリクエスト仕様書としてcurlコマンドのご提案
90 -5 @mima_ita 4822 +483 99 48.7071 610 12.6504% あなたのおっしゃるレビューってどのことかしら?
91 -13 @kuni-nakaji 4821 +337 17 283.588 2278 47.2516% httpsだからというだけで安全?調べたら怖くなってきたSSLの話! ?
92 +5 @k0kubun 4816 +801 59 81.6271 1035 21.4909% ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い
93 @nonbiri15 4812 233 20.6524 980 20.3658% 優秀な技術者を追い出してしまう方法
94 @zaburo 4737 221 21.4344 375 7.9164% gitでシンプルなデプロイ環境を作る
95 @shuntaro_tamura 4717 63 74.873 654 13.8647% フロントエンド、サーバサイド、インフラの具体例
96 -19 @m-yamashita 4703 +195 13 361.769 3491 74.2292% 初心者向け、「上手い」シェルスクリプトの書き方メモ
97 -16 @hachi8833 4688 +251 45 104.178 2704 57.6792% Vim幼稚園からVim小学校へ
98 @takahirom 4622 72 64.1944 383 8.28646% AndroidStudioのPostfix Completionで爆速コーディング
99 -6 @konifar 4564 +511 98 46.5714 255 5.5872% Android Studioのgradleビルドを高速化する
100 @hashrock 4557 26 175.269 1040 22.822% 脱Bootstrapガイド ~フルスクラッチCSS~

僕も 55位 にランクイン。やったッ...!やったッ...!

TOP100順位の上下

昨年データと比較した、順位の上下についてみてみます。

上昇 下降 維持 新規
43 42 4 11

全体の1割が入れ替わり、それ以外の9割は概ね上がったり下がったりが拮抗しているようです。

また、100位以内で最も上昇幅が大きかったのが @Hironsan でした。
2017年のContributionは+3278ですが、新規記事の中では最もいいねの多い 自然言語処理における前処理の種類とその威力 ですが、集計時点で839いいねであるので、増分の約1/4程度です。
そのため、増加分の多くは既存の記事で伸ばしたことになりますが、 機械学習系の記事 を多く書かれているようなので、このあたりが今年大きく伸びたものと思われます。トレンドを感じますね。

Contributionの分布

Qiitaアカウントがトータル20万ある中で、全体はどのようなContribution分布をしているのでしょうか。
シェル芸を駆使して値の範囲ごとに数を出してみます。sedオタクみたいになってしまいました。

Contribution範囲ごとの人数分布
$ cat qiita_data.csv | cut -d , -f 3 | sed -e 's/^$/=/' -e 's/^0$/_/' -e 's/[0-9]/*/g' | sort | uniq -c | sed -e 's/ \*/ 1/g' -e 's/\*/0/g' -e 's/=/none/' -e 's/_/0/' | sed -E 's/([0-9]+) (1[0]*)/\1 \2-/g' | awk '{OFS="\t"}{print $2,$1}'
none    2247
0       169576
1-      10701
10-     11985
100-    5516
1000-   851
10000-  26

noneとなっているのはデータが取れなかったアカウントです。いわゆる凍結アカウントですね。
次にこのデータをもとにグラフを作ります。シェル芸人はExcelなどに頼らず gnuplot を使います。

gnuplotのインストール
$ sudo apt-get install gnuplot

楽チンです。
グラフの描画をスクリプトで多少指定しつつ、先ほどの結果を投入した contribution_stat.dat を食わせます。

Contributions×Usersグラフの生成
$ cat contribution_stat.plt
# png形式で出力
set terminal pngcairo
# 出力パス&ファイル名を指定
set output "contribution_graph.png"
# インプットのデリミタを指定(デフォルトはスペース)
set datafile separator "\t"
# 境界線のスタイルを指定
set style fill solid border lc rgb "#00FA9A"

# ラベルとフォントを指定
set xlabel 'Contributions'
set ylabel 'Users'
set font "DejaVuSansMono,14"

# 指定ファイルのデータを元にグラフをプロット
plot "contribution_stat.dat" using 0:2:xtic(1) with boxes lw 2 lc rgb "#00FA9A" notitle

$ gnuplot -c contribution_stat.plt

できました。

out.png

ううむ...。
なにはともあれ具体的な数値にすると以下となります。

Contribution数 ユーザ数 比率
なし 2247 1.11846%
0 169576 84.4073%
1- 10701 5.32648%
10- 11985 5.9656%
100- 5516 2.74562%
1000- 851 0.42359%
10000- 26 0.0129416%

このように、全体の1%が凍結アカウント、 84%がContribution数0 のようでした。
なのでQiitaのContributionが1以上ある人は「 俺、Qiitaの上位15%なんだよね...(遠い目) 」って言う権利があります!

ちなみに凍結アカウントを除いた全アカウントにおいては、

有効アカウント数 総Contribution 平均Contribution
198,655 4,560,820 22.9585

であり、さらにContribution数が1以上のアカウントをアクティブアカウントとして区別すると、

アクティブアカウント数 総Contribution 平均Contribution
29,079 4,560,820 156.8424

という結果となります。

ユーザ別記事数ランキング

ここからはおまけです。20位くらいまで出してみましょう。

ユーザ別記事数ランキング
$ cat qiita_data.csv | sort -k 2nr,2 -t , | awk -F"," 'BEGIN{OFS="|"}{TOP_ITEM=substr($5,0,index($5,"):")) ; print "|"NR,"@"$1,$2,$3,TOP_ITEM"|"}' | head -n 20
ランク ユーザ名 記事数 Contribution数 Top記事
1 @7of9 5035 3906 Qiita > 「いいね」機能についての要望
2 @tukiyo3 1555 9301 たくさんあるオープンソースライセンスのそれぞれの特徴のまとめ
3 @tbpgr 728 7240 Markdown記法 サンプル集
4 @suin 697 22531 【まとめ】これ知らないプログラマって損してんなって思う汎用的なツール 100超
5 @ohisama@github 508 399 ウィルスと闘ってみた。
6 @chen7897499 457 64 rails devise
7 @tcsh 383 1231 [JAWS-UG CLI] ハンズオン一覧
8 @snaka 375 3096 rails console の tips
9 @edo_m18 372 12634 WebのUIテスト自動化 - Seleniumを使ってみる
10 @hshimo 307 10021 プログラマが独立・起業する時によくするミスと対策 まとめ
11 @ironsand 292 2357 git push -u オプションの意味
12 @masato 273 2455 React入門 - Part2: Browserify/Reactify/Gulpを使う
13 @cielavenir 272 591 El Capitan移行メモ
14 @n0bisuke 266 6583 3行のソースコードを入れるだけで機械学習できると噂のindicoをNode.jsで使って機械学習入門してみ る
15 @pugiemonn 265 5144 こんなHTMLとCSSのコーディング規約で書きたい
16 @jkr_2255 263 2921 セッション管理の要注意点
17 @Nabetani 263 953 C++ の、スマートだと思う人がいるかもしれないコードの書き方12選のつもりが6個ぐらいで断念
18 @ngyuki 258 4003 AngularJS でログインのフローを作る
19 @YumaInaura 258 1004 拝啓 本当は Qiita を書きたいのに、まだ迷っているあなたへ。
20 @mpyw 257 17052 PHPでデータベースに接続するときのまとめ

なんか、すごいですね。
@7of9 さんが異次元すぎる。およそ上位10人を足しても1人分な感じ。

ユーザ別フォロワー数ランキング

さっきのシェル芸で指定していたカラムを1種類ずらすだけ。

ユーザ別フォロワー数ランキング
$ cat qiita_data.csv | sort -k 4nr,4 -t , | awk -F"," 'BEGIN{OFS="|"}{TOP_ITEM=substr($5,0,index($5,"):")) ; print "|"NR,"@"$1,$4,$3,TOP_ITEM"|"}' | head -n 20
ランク ユーザ名 フォロワー数 Contribution数 Top記事
1 @hirokidaichi 2148 33183 ペアプログラミングして気がついた新人プログラマの成長を阻害する悪習
2 @jnchito 1973 33833 モデルやメソッドに名前を付けるときは英語の品詞に気をつけよう
3 @taguchi 1885 0
4 @dankogai 1828 2891 Swiftで面倒なJSONの取り扱いをさらに10倍便利にするclass JSON
5 @mizchi 1777 17591 春からはじめるモダンJavaScript / ES2015
6 @yukihiro_matz 1604 104 24時間一人mrubyハッカソン
7 @supermomonga 1594 812 PHPとしても実行できるRubyの書きかた
8 @icoxfog417 1434 27896 Pythonを書き始める前に見るべきTips
9 @mpyw 1362 17052 PHPでデータベースに接続するときのまとめ
10 @shu223 1322 19843 ディープラーニングの有名ライブラリ5種を最短距離で試す半日コース(TensorFlow, Chainer, Caffe, DeepDream, 画風変換)
11 @kenmatsu4 1133 9990 【機械学習】ディープラーニング フレームワークChainerを試しながら解説してみる。
12 @hyuki 1109 157 Vimで、文字列を別のところに「持って行って置換する」効率的な方法は?
13 @mattn 1109 2318 本物の golang を... 本物の Gopher を、お見せしますよ。
14 @naoya@github 1090 3127 React Native ファーストインプレッション
15 @kensuu 1033 0
16 @joker1007 1013 9539 てめえらのRailsはオブジェクト指向じゃねえ!まずはCallbackクラス、Validatorクラスを活用しろ !
17 @masuidrive 985 3230 OSXでDockerを超高速化するdinghy
18 @kazunori279 981 11636 Cloud Vision APIの凄さを伝えるべくRasPi botとビデオを作った話
19 @vvakame 945 7634 Gradle入門
20 @Qiita 929 7385 Markdown記法 チートシート

概ねContributionの数に連動するフォロワー数になるのかなと思っていたらずいぶん違いますね。
普通にミスったかと思いましたが、 Contributionが0でもフォロワー1000以上の人がいる なんて想像もしませんでした。すごい。

ちょっと面白かったので、 Contribution数とフォロワー数で可視化 してみます。

Contributionとフォロワー数のデータ
$ cat qiita_data.csv | sort -k 4nr,4 -t , | cut -d , -f 3,4 | head -n 100 | tr "," "\t"
33183   2148
33833   1973
0       1885
2891    1828
17591   1777
104     1604
812     1594
27896   1434
17052   1362
19843   1322
()

フォロワー数上位100アカウントをこういう形式で follower_stat.dat に取って、

Contributions×Followersグラフの生成
$ cat follower_stat.plt
# png形式で出力
set terminal pngcairo
# 出力パス&ファイル名を指定
set output "/follower_stat.png"
# インプットのデリミタを指定(デフォルトはスペース)
set datafile separator "\t"

# ラベルとフォントを指定
set xlabel 'Contributions'
set ylabel 'Followers'
set font "DejaVuSansMono,14"

# 指定データに対する近似直線を計算
fit a*x+b "follower_stat.dat" via a,b
# 指定データを用いてグラフ(データ点と近似直線)をプロット
plot "follower_stat.dat" ps 1 pt 7 lc rgb "#00FA9A" notitle, a*x+b lw 2 lc rgb "#6495ED" title sprintf("%0.2fx+%0.2f",a,b)

$ gnuplot -c follower_stat.plt

として完成です。地味に近似曲線を入れています。

follower_stat.png

上位100アカウントで取っているため左下が空いていますが、大局的な見え方は上位100アカウントで十分そうでした。
(これ以上増やしても左下に点が集まるばかりで散らばりの印象はほぼ変わりません)

グラフ上にも書いてありますが、上位100アカウントに対する近似直線は 0.02x + 517.68 となるようです。gnuplotの万能さがやばい。
近似直線と比べてみると、上側で突出している特異な点がよりわかりやすくなりますね。

散らばりのイメージ自体は上の通りですが、近似直線の切片が大きく出ているように、やはり下位を評価対象から外すのはよくありません。
改めてContribution数が1以上のアクティブアカウントにおけるグラフを生成してみましょう。

follower_stat.png

やはり左下に点が集中します。
が、近似直線のもっともらしさは上がったのではないでしょうか。

僕自身は現在 6767 Contributionに対して、フォロワー数が171ですので、近似直線の下側に位置するようです。
近似直線の真上にくる場合、フォロワー数およそ342となるContributionですので、ちょうど半分くらいのフォロワーしかいない計算です。
近似直線を境として、その上下でどういう性質に差があるのかは考えてみたいですね。

記事別分析

family_shinbun.png

それでは最後に記事別にみてみましょう。

総記事数

Qiitaユーザ20万に対して記事は一体どれくらいあるのでしょうか。
1人で1000記事書いている人もいるくらいですからもしかすると...。

$ cat qiita_data.csv | awk -F"," 'BEGIN{SUM=0}{SUM+=$2}END{print SUM}'
260428

おやおやといった感じですね。1アカウントあたり 1.29 です。
しかしこちらも0記事のアカウントが多くあると推測されるため、分布をみてみましょう。
gnuplotのスクリプトはContribution分布のときとほぼ変わらないので折りたたんでおきます。

item_stat.plt
# png形式で出力
set terminal pngcairo
# 出力パス&ファイル名を指定
set output "item_stat.png"
# インプットのデリミタを指定(デフォルトはスペース)
set datafile separator "\t"
# 境界線のスタイルを指定
set style fill solid border lc rgb "#00FA9A"

# ラベルとフォントを指定
set xlabel 'Items'
set ylabel 'Users'
set font "DejaVuSansMono,14"

# 指定ファイルのデータを元にグラフをプロット
plot "item_stat.dat" using 0:2:xtic(1) with boxes lw 2 lc rgb "#00FA9A" notitle

item_stat.png

記事数 ユーザ数 比率
なし 2247 1.11846%
0 168427 83.8354%
1- 23553 11.7236%
10- 6496 3.23342%
100- 177 0.0881027%
1000- 2 0.00099551%

こちらもContribution同様、約85%の方が記事数0のようです。
1つ以上記事を書いている人(30,228)に絞れば、 平均記事数8.6155 となりました。

記事別いいねランキング

意外となかった記事のランキング。
でも確かに上位のものは大体見たことありますね。

ランク いいね数 記事
1 6106 ロシアの天才ハッカーによる【新人エンジニアサバイバルガイド】
2 5937 Markdown記法 チートシート
3 5637 非デザイナーエンジニアが一人でWebサービスを作るときに便利なツール32選
4 5041 ペアプログラミングして気がついた新人プログラマの成長を阻害する悪習
5 4707 うまくメソッド名を付けるための参考情報
6 4542 Gitでやらかした時に使える19個の奥義
7 4514 数学を避けてきた社会人プログラマが機械学習の勉強を始める際の最短経路
8 4328 【まとめ】これ知らないプログラマって損してんなって思う汎用的なツール 100超
9 4169 旧石器時代のJavaScriptを書いてる各位に告ぐ、現代的なJavaScript超入門 Section1 ~すぐにでも現代っぽく出来るワンポイントまとめ~
10 4073 もう保守されない画面遷移図は嫌なので、UI Flow図を簡単にマークダウンぽく書くエディタ作った
11 3688 新人プログラマに知っておいてもらいたい人類がオブジェクト指向を手に入れるまでの軌跡
12 3568 インフラエンジニアとしてよく使うコマンド集
13 3491 初心者向け、「上手い」シェルスクリプトの書き方メモ
14 3368 ネイティブと働いて分かった英語コミットメッセージの頻出動詞10つ
15 3141 特にプログラマーでもデータサイエンティストで ないけど、Tensorflowを1ヶ月触ったので超分かりやすく解説
16 3098 コードを書く際の指針として見返すサイトまとめ
17 3054 そこそこセキュアなlinuxサーバーを作る
18 3018 何かのときにすっと出したい、プログラミングに関する法則・原則一覧
19 2986 翻訳: WebAPI 設計のベストプラクティス
20 2951 2016年 独りで新規WEBサービスを開発・運用した際の知見
21 2891 Pythonを書き始める前に見るべきTips
22 2828 プログラミングでよく使う英単語のまとめ【随時更新】
23 2781 インフラエンジニアじゃなくても押さえておきたいSSHの基礎知識
24 2748 Reactを使うとなぜjQueryが要らなくなるのか
25 2704 モデルやメソッドに名前を付けるときは英語の品詞に気をつけよう
26 2704 Vim幼稚園からVim小学校へ
27 2696 オブジェクト指向と10年戦ってわかったこと
28 2669 Gitのコミットメッセージの書き方
29 2585 エンジニアなら知っておきたい、絵で見てわかるセキュア通信の基本
30 2581 誰も教えてくれなかったMySQLの障害解析方法
31 2578 プログラマが独立・起業する時によくするミスと対策 まとめ
32 2571 英語コミットコメントに使えるオシャレフレーズ集
33 2554 Linux開発環境の基礎知識
34 2492 画像処理の数式を見て石になった時のための、金の針
35 2466 最近の行儀のよい JavaScript の書き方
36 2425 GitHubで使われている実用英語コメント集
37 2411 不安とストレスから解放される見積りとスケジュール方法
38 2381 中上級者になるためのJavaScript【知識編】
39 2339 [初心者向け] RubyやRailsでリファクタリングに使えそうなイディオムとか便利メソッドとか
40 2289 日本の行政機関等が公開しているAPIについてのまとめ(2016年8月17日暫定版。随時更新)
41 2284 エンジニアで稼ぐために大切な19のコト
42 2282 脱初心者を目指すなら知っておきたい便利なVimコマンド25選 (Vimmerレベル診断付き)
43 2278 httpsだからというだけで安全?調べたら怖くなってきたSSLの話!?
44 2261 30分で出来る、JavaScript (Electron) でデスクトップアプリを作って配布するまで
45 2247 質問は恥ではないし役に立つ
46 2179 You Don't Need jQuery
47 2178 WebAPIでエラーをどう表現すべき?15のサービスを調査してみた
48 2158 VagrantとDockerについて名前しか知らなかったので試した
49 2128 クラスの命名のアンチパターン
50 2117 npm とか bower とか一体何なんだよ!Javascript 界隈の文脈を理解しよう
51 2102 英語のコメントや issue で頻出する略語の意味 (FYI, AFAIK, ...)
52 2098 あなたのサーバは本当に安全ですか?今もっともイケてる脆弱性検知ツールVulsを使ってみた
53 2070 iOSでこんなアプリ,こんな機能を作りたかったらこれを見ろ!作りたいアプリに対応するクラス、フレームワーク、ラ イブラリのまとめ!
54 2068 AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ
55 2055 PHPでデータベースに接続するときのまとめ
56 2055 ゼロからDeepまで学ぶ強化学習
57 2037 データサイエンティストを目指す人のpython環境構築 2016
58 2032 最強のSSH踏み台設定
59 1993 「AWS is 何」を3行でまとめてみるよ
60 1989 究極のIT系最新技術情報収集用Slackチーム公開 - モヒカンSlack -
61 1978 Electronでアプリケーションを作ってみよう
62 1969 JavaScriptを読んでて「なにこれ!?」と思うけれど調べられない記法8選。
63 1968 もう逃げない。HTMLのviewportをちゃんと理解する
64 1968 Go言語の初心者が見ると幸せになれる場所 #golang
65 1965 ライセンスの選択を恐れる必要はありません
66 1956 使えるRSpec入門・その1「RSpecの基本的な構文や便利な機能を理解する」
67 1946 Markdownテキストでシーケンス図とフローチャートを描く
68 1941 Swiftで作られたイケてるUIライブラリたち
69 1939 Javaを使うなら知っておきたい技術、フレームワーク、ライブラリ、ツールまとめ
70 1932 ここ数年前から2015/5までのモダンフロントエンドを総まとめしてみた
71 1884 エンジニアとして成長するべく私が実践している学習方法
72 1881 春からはじめるモダンJavaScript / ES2015
73 1880 2017年のフロントエンドエンジニアならこの程度は知ってて当然だよな?
74 1871 Git・GitHubに隠された便利な機能 GitHub Cheat Sheet(日本語訳)
75 1870 プレゼンテーションに使う画像の探し方
76 1858 読んで良かった基礎知識の入門書
77 1855 Android開発を受注したからKotlinをガッツリ使ってみたら最高だった
78 1841 そろそろ真面目に、HTMLで帳票を描く話をしようか
79 1835 UIセンスが壊滅的なエンジニアがそれっぽいwebアプリを作るために使った無料UIライブラリをまとめておく
80 1827 なぜ仮想DOMという概念が俺達の魂を震えさせるのか
81 1788 初心者エンジニアにおすすめしたい「進捗どうなった?」と言われないための仕事の進め方
82 1747 [iOS] 新言語SwiftがObjective-Cよりも良いところ
83 1735 iOSの開発でお気に入りのライブラリN選
84 1731 Gitのこれやめて!リスト
85 1725 ゼロから始めるJavaScript生活
86 1683 外国人が語る:英語でクラスやメソッド等の名付け方
87 1679 Naming -名前付け-
88 1660 クソコードにならない為に、これだけは守って欲しい7つのこと
89 1653 【機械学習】ディープラーニング フレームワークChainerを試しながら解説してみる。
90 1653 新米エンジニアが入社して半年で読んだ・読まされた本まとめ
91 1646 0から始めるAWS入門:概要
92 1636 デザイナーに言われた「非デザイナーが気をつけるべきデザインの4原則」
93 1630 エンジニアのための「Sketch入門!」 1時間コース
94 1627 アプリ開発で参考にしておきたい UI デザインパターンまとめサイトのまとめ
95 1616 SEO嫌いにお送りするSEO策。これでもうSEOについてしばらく考えなくて良いぜ!!
96 1598 開発フロー研修 @ Wantedly
97 1598 Webフロントエンド表示速度、最速化手法まとめ
98 1591 技術的負債とどうやって戦うか
99 1585 新卒の子にどこまで勉強すれば良いですかね?と聞かれた件
100 1584 Dockerで即実行できる、社内・自宅向けオープンソースWebアプリ

自分の記事の中でも 不思議の国のSE用語 が一番好きなんですけどあと一息で入りませんでしたね。惜しい。
ちなみにこの上位100位のうち、複数記事がランクインされたのが以下の方々です。うーん、レジェンド。

ランクイン数 ユーザ名
5 @hirokidaichi
4 @jnchito
3 @icoxfog417
2 @suin
2 @muran001
2 @mizchi
2 @kenju

記事別分析の問題点

さて、出しておいてなんですが、上記の記事別分析には問題があります。
今回のデータ集めでは、ユーザ名をベースにユーザトップから各種情報を抜き出し、ついでにユーザごとのTOP5記事の情報を取得しています。
記事に関してはさすがに全データを集めるのが大変(だしサーバ負荷も相当)なので、ランキングを出せればいいやということでTOP5情報しか持たずに上記のランキングを生成しています。

が、複数記事ランキングで1つだけ気になる点があり、 @hirokidaichi さんがTOP100に5つランクインしています。
これはもしやと思い、 ユーザトップ から記事一覧を眺めていると、やはりTOP5以外でも全体のTOP100に入る記事があるではありませんか。。。
それもそのはず、個人TOP5の第5位にあたる 不安とストレスから解放される見積りとスケジュール方法 ですら、収集当時で 2411いいね となっており、これは全体でも37位にあたります。余裕のTOP100。

なので改めて、TOP100におけるボーダーが 1584いいね であることを念頭におけば、

が更に入ることになり、 TOP100へのランクイン数は8 となります。恐ろしい。

今回のスポンサーたち

money_narikin.png

今回いろんな分析をするにあたり、実はそんなに多くのシェル芸パターンを使っているわけではありません。
ハタから見ると長いだけなので、今回使ったもののエッセンスだけをいくつか抜粋したいと思います。

ソート

今回はランキング、それもいくつかの切り口でのランキングですから、ソートは非常に活躍しました。
今回はCSVデータを降順ソートする事がほとんどでしたので、例えば第3カラムをソートする場合だとイディオム的には

ソート
$ (なにかのデータ) | sort -t , -k 3nr,3

みたいなものが基本の形になります。
-k ではソート列の情報を表し、 nr数字(numeric)の降順(reverse)ソート の表現にあたります。
なんで3が2回も出て来るのって疑問はありますが、実用上はそんなに気にしなくてもよいでしょう...。2回です。2回。
気になる人は man sort を読んでみてください。 要は「ごっちゃになるからちゃんと指定しろ」ってことです。

抽出

CSVから特定カラムの情報を抽出したいときもあるでしょう。
第3カラムを抽出する場合には以下のようになります。

抽出
$ (なにかのデータ) | cut -d , -k 3

こちらはデリミタ指定が -d オプションになっているので非常に素直ですね。

カウント

分布などを調べる場合には値ごとのカウントが必要になります。
カウントする値が流れてくるケースでは、

カウント
$ (なにかのデータ) | sort | uniq -c

というようになります。
sort を挟んで整列させないとカウントがおかしくなるので基本的にはこういうコマンドだと思うのがよいでしょう。

計算

平均や合計など、各行の値を横断して計算したいときもあるでしょう。
そうした場合にはそろそろ awk が使えます。

計算
$ (なにかのデータ) | awk -F"," 'BEGIN{SUM=0}{SUM+=$1}END{print "SUM: "SUM", AVERAGE: "SUM/NR}'

awkの場合はデリミタ指定が -F です。
awkの中は言語のようになっているので、結構色んなことができます。ワンライナーでしか使わないことのほうが多いと思いますが、スクリプトファイルに外出すると途端に夢が広がるかもしれません。
ENDブロックで使っている NR は、参照先の行数を表す特殊変数ですが、ENDブロックの時点では最終行に達していますから、ここのNRはインプットの行数を表すものになります。そのため、 SUM/NR が平均として機能するわけですね。

また他にも、ソート済みストリームを整列したりするときにNRを一緒に出しておくと、それが順位の代わりになったりもして便利です。

整形/整列

色々なデータをパイプで受け取れる各種コマンドでしたが、アウトプットもコマンドによって様々です。
記事にするにあたり、当然表にして出したいのですが、Markdownの表におけるデリミタは | であることと列の順序もいじりたかったりするため、ここを工夫しなければなりません。
そういうときにもawkが活躍してくれます。

$ (なにかのデータ) | awk -F"," 'BEGIN{OFS="|"}{print "|"$2,$1"|"}'

awkで複数フィールドを出力する際はデフォルトでスペースが用いられますが、 OFS 変数に好きなものを入れてやるとその区切りで出力してくれます。
行頭と行末には入れてくれないので自分で足しているのが少しかっこ悪く思いますが、まぁこれくらいならいいでしょう。
あとはカラムの順序を入れ替えるのも簡単でいいですね。ありがとう、awk。

おわりに

kabu.png

今回もデータを 取得する部分、分析する部分、可視化する部分 それぞれでシェルが大活躍してくれました。
2017年何をしたってわけでもないですが、人よりはシェルに親しんでいることもあり、昨年よりはかなりスムーズにシェルを叩いていけたような気がしました。
とはいえ、データをCSV(カンマ区切り)で集めておきながら、データ中に一部カンマが入っていたりして、分析時にかっこわるいことをしたりと苦労しました。
また来年も同じようなことをするとなれば、もう少し華麗にできるよう、データ収集から気を使っておきたいなと思いました。

あと、自分のモチベーションでgnuplotを使ったのは割と今回がはじめてに近かったのですが、これはすばらしいですね。
グラフ系って結構微調整が面倒だったりするんですが、スクリプトファイルにして直して再実行がたいへん楽。
シェルで分析してCSVにしつつ、 Excelでぽちぽちグラフに起こすなんていう不毛なこと をしていた自分を恥じたい気分です。

それではみなさま良いお年を。