LoginSignup
4
3

More than 3 years have passed since last update.

Qiitaのタグを2018/12~2019/3の記事数、フォロワー数、いいね数で比較してみた

Last updated at Posted at 2019-05-26

※tag1216さんの指摘により、集計期間間違っていることに気付いたので、タイトル等を修正しました。

先日、「Qiitaタグの記事数とフォロワー数を比較してみた」を初投稿した。
投稿後に自身の関連記事を見てみると、、
最上位の記事「Qiitaの投稿をNVD3で可視化してみるとRuby人気なんだなと改めて分かった。」と、グラフの形式が完全に被っていることと、グラフの見やすさも私の方が劣っていた。
正規化や、記事投稿の動機の1つにもなった「#migrated」などオリジナルな観点もあったけど。

そのため、今回は下記、投稿後に思った下記改善を考慮し、完全オリジナルな内容にアップデートする。

  • 全数では5年以上のデータとなり、トレンドがわからないため、2018/12~2019/3のデータでグラフを作成する。フォロワーは、集計期間に記事を投稿したユーザのみを対象とする。
  • バブルチャートでは3軸の可視化ができるため、いいね数も評価する。
  • 傾向からグループを決定してチャートの色分けを行う。
  • chart.jsがスマホ環境では崩れていたため、不要なラベルを消してスマホでも結果を見やすくする。

やったこと

  • Qiita apiの記事一覧を日付毎に2018/12~2019/3まで取得し、タグ毎の記事数と、タグ毎のいいね数、投稿ユーザ一覧を集計する。
  • 上記で取得した全てのユーザについて、フォローしているタグを集計し、タグ毎のフォロワー数を集計する。(今回投稿ユーザが15,178ユーザいたので、1,000回/1hのAPI制限があるので、15時間以上APIを動かし続けてデータを取得した)
  • 記事数、フォロワー数、いいね数を、正規化し、同じ重み付けで上位10を決定し、前回の全数のランキングと比較する
  • 上位100について、記事数、フォロワー数、いいね数の傾向でタグを19個のグループに分ける
  • 上位100について、バブルチャートで、いいね数を大きさで表して、グループ毎に色分けしてグラフ化する。

結果

総タグ数: 15,649,
総記事数: 43,684,
総投稿者数: 15,178,
総タグ記事数: 12,1912,
総タグフォロワー数: 91,046,
総タグいいね数: 1,307,100

集計方法の変更による違い(全数 vs 2018/12~2019/3)

前回記事と順位の差異を含めて下記の通り。

前回記事と比較して、フォロワー数側に大きく変化が生じたのは、フォロワー数をその期間に記事を投稿している人に限っているのが大きいかもしれないが、前回の結果はフォロワー数側に引っ張られて評価値順位が高いものもあったため、今回の修正は妥当(期間を区切った集計の方が有意な結果となる)だと考える。

なお、Railsが評価+8は少し意外だが、それだけRailsのフォロワーに投稿者が多いのではないかと推測する。

タグ名 評価値順位 フォロワー数順位 記事数順位 評価値(%) フォロワー数 記事数 評価値差分(%)
Python 1(+1) 1(+1) 1(-) 3.35 3175 3928 0.27
JavaScript 2(-1) 2(-1) 2(-) 2.76 3106 2583 1.29
Ruby 3(-) 4(+10) 3(-) 1.72 1829 1747 0.58
PHP 4(-) 9(-) 6(-2) 1.48 1642 1405 0.65
Rails 5(+8) 15(+14) 4(+1) 1.40 1355 1603 0.17
Java 6(-1) 6(+1) 12(-3) 1.34 1715 972 1.09
GitHub 7(+3) 3(+2) 30(-) 1.33 2032 522 1.80
Git 8(+3) 5(+8) 21(-7) 1.28 1812 689 1.43
Linux 9(-1) 8(+4) 18(-6) 1.28 1709 826 1.20
Android 10(-4) 13(-2) 14(-6) 1.19 1471 927 0.86

いいね数も含めたTOP100

タグ名 評価値順位 フォロワー数順位 記事数順位 いいね数順位 評価値 フォロワー数 記事数 いいね数
Python 1 1 1 2 3.54 3175 3928 51004
JavaScript 2 2 2 1 3.25 3106 2583 55042
Ruby 3 4 3 14 1.43 1829 1747 10901
PHP 4 9 6 18 1.22 1642 1405 9305
Rails 5 15 4 24 1.16 1355 1603 8946
HTML 6 7 28 6 1.14 1710 544 14513
Git 7 5 21 22 1.08 1812 689 9142
Vue.js 8 41 13 3 1.07 587 966 23240
Linux 9 8 18 27 1.06 1709 826 8186
Java 10 6 12 35 1.04 1715 972 5684
GitHub 11 3 30 36 1.03 2032 522 5666
CSS 12 11 24 12 1.02 1518 633 11473
AWS 13 29 5 16 1.01 869 1597 10088
Docker 14 26 8 8 1.01 931 1187 13399
Node.js 15 14 17 20 0.99 1412 851 9250
Android 16 13 14 30 0.98 1471 927 7521
iOS 17 18 11 9 0.98 1122 975 11733
機械学習 18 40 20 4 0.91 597 765 18793
C++ 19 24 23 17 0.77 978 636 9339
初心者 20 101 9 5 0.77 125 1012 17543
C# 21 23 16 32 0.76 994 857 6222
Swift 22 37 10 29 0.72 688 980 7880
Go 23 36 19 26 0.69 697 786 8723
HTML5 24 10 68 82 0.69 1525 225 2700
Mac 25 21 22 52 0.67 1083 640 3708
MySQL 26 16 27 161 0.65 1260 556 1546
Python3 27 62 7 28 0.65 314 1210 7945
Qiita 28 12 88 142 0.65 1508 182 1731
Unity 29 48 15 25 0.62 422 864 8859
DeepLearning 30 52 32 7 0.61 372 491 13471
TypeScript 31 49 29 11 0.60 417 540 11608
Vim 32 17 59 53 0.58 1145 260 3696
React 33 45 26 19 0.58 483 621 9264
jQuery 34 19 54 56 0.57 1107 265 3667
Firebase 35 65 37 10 0.53 303 428 11687
Chrome 36 25 86 51 0.50 962 183 3735
iPhone 37 20 193 123 0.48 1106 84 1930
新人プログラマ応援 38 67 55 13 0.46 258 263 11383
Xcode 39 32 41 92 0.45 779 350 2536
Twitter 40 30 92 75 0.44 863 170 2939
CSS3 41 22 174 167 0.43 1002 94 1429
Ubuntu 42 34 38 285 0.42 767 427 816
Laravel 43 63 25 41 0.41 309 632 4765
C 44 33 52 118 0.41 768 266 2049
kubernetes 45 58 31 37 0.40 335 494 5651
ポエム 46 123 43 15 0.39 85 338 10632
MacOSX 47 27 96 567 0.39 909 165 332
RaspberryPi 48 59 34 42 0.37 332 463 4734
CentOS 49 35 52 215 0.37 727 266 1109
ShellScript 50 31 114 575 0.36 846 146 329
正規表現 51 28 188 473 0.36 877 87 418
Kotlin 52 53 35 74 0.33 366 446 3023
自然言語処理 53 91 106 23 0.32 138 155 9032
TensorFlow 54 57 55 43 0.31 338 263 4628
Heroku 55 46 44 119 0.31 465 309 2040
nuxt.js 56 91 44 31 0.31 138 309 6682
VSCode 57 68 42 40 0.30 231 344 4798
golang 58 51 47 73 0.30 382 300 3032
MachineLearning 59 75 58 33 0.30 190 262 6096
SSH 60 38 115 420 0.29 656 145 498
Apache 61 39 118 599 0.29 654 138 314
個人開発 62 214 167 21 0.28 44 99 9247
nginx 63 42 85 398 0.28 578 185 543
Slack 64 69 49 55 0.26 228 288 3688
Scala 65 44 90 214 0.26 487 178 1113
Django 66 71 36 111 0.25 198 433 2175
Rust 67 65 79 98 0.23 303 198 2448
Windows 68 124 33 101 0.22 84 475 2403
Haskell 69 50 156 139 0.22 390 105 1741
gcp 70 83 47 71 0.22 149 300 3095
Keras 71 80 65 54 0.22 162 226 3689
Emacs 72 47 187 257 0.21 457 88 924
docker-compose 73 181 64 39 0.21 53 242 5072
数学 74 89 82 45 0.21 139 189 4394
Objective-C 75 43 360 421 0.21 504 45 492
SQL 76 98 39 134 0.19 129 371 1797
lambda 77 107 40 126 0.19 109 359 1914
OpenCV 78 84 65 77 0.19 147 226 2778
GoogleAppsScript 79 78 63 106 0.19 167 243 2281
Bash 80 98 55 87 0.18 129 263 2581
Elixir 81 72 74 110 0.18 197 205 2177
Flutter 82 85 70 93 0.18 143 217 2534
ネタ 83 500 379 34 0.17 14 43 6037
Elm 84 107 128 60 0.17 109 131 3631
Zsh 85 55 273 262 0.17 348 61 898
競技プログラミング 86 121 80 68 0.17 89 193 3193
IoT 87 96 59 131 0.17 132 260 1843
MongoDB 88 56 202 329 0.17 341 82 705
Azure 89 86 46 205 0.16 142 301 1163
データ分析 90 130 109 62 0.16 79 154 3571
設計 91 262 308 38 0.16 33 53 5262
アルゴリズム 92 130 124 64 0.16 79 134 3517
UX 93 248 188 44 0.15 36 87 4563
初心者向け 94 901 106 46 0.15 6 155 4235
GoogleCloudPlatform 95 93 76 130 0.15 135 202 1848
pandas 96 146 74 79 0.15 66 205 2754
R 97 77 78 192 0.15 170 200 1268
PostgreSQL 98 94 51 287 0.15 134 280 801
api 99 199 68 89 0.14 47 225 2572
AI 100 194 119 65 0.14 48 136 3501

グループの決定

多次元データ分析に全く詳しくないため、直感的にフォロワー数/記事数/いいね値数の一部が多いもの一部が少ないもので下記の(6 * 3) + 1 = 19グループに分ける
※判定は+や-数が多い順に行う

グループ名 判定内容 タグ(TOP100内) 補足
いいね+++ rgba(255, 0, 0, 0.5) いいねの割合が一番高く、
他のポイントの2.5倍以上
DeepLearning
Firebase
新人プログラマ応援
ポエム
自然言語処理
個人開発
ネタ
設計
UX
初心者向け
記事数/フォロワー数の割にいいねが多い?
いいね++ rgba(191, 0, 0, 0.4) いいねの割合が一番高く、
他のポイントの1.6倍以上
Vue.js
機械学習
TypeScript
nuxt.js
MachineLearning
数学
Elm
データ分析
アルゴリズム
AI
記事数/フォロワー数の割にいいねが多い?
いいね+ rgba(127, 0, 0, 0.3) いいねの割合が一番高く、
他のポイントの1.1倍以上
Python
React
VSCode
Slack
Keras
OpenCV
記事数/フォロワー数の割にいいねが多い?
フォロワー+++ rgba(0, 0, 255, 0.5) フォロワーの割合が一番高く、
他のポイントの2.5倍以上
Git
Linux
GitHub
HTML5
MySQL
Qiita
Vim
jQuery
Chrome
iPhone
Xcode
Twitter
CSS3
C
MacOSX
CentOS
ShellScript
正規表現
SSH
Apache
nginx
Scala
Haskell
Emacs
Objective-C
Zsh
MongoDB
記事数/記事内容共に不足している?
フォロワー++ rgba(0, 0, 191, 0.4) フォロワーの割合が一番高く、
他のポイントの1.6倍以上
HTML
Java
CSS
Node.js
Android
Mac
Heroku
golang
Rust
記事数/記事内容共に不足している?
フォロワー+ rgba(0, 0, 127, 0.3) フォロワーのポイントが一番高く、
他のポイントの1.1倍以上
iOS
C++
C#
Go
Elixir
記事数/記事内容共に不足している?
記事数+++ rgba(0, 255, 0, 0.5) 記事数の割合が一番高く、
他のポイントの2.5倍以上
- フォロワーが少なく、いいねがもらいにくい?
記事数++ rgba(0, 191, 0, 0.4) 記事数の割合が一番高く、
他のポイントの1.6倍以上
Python3
Django
Windows
SQL
lambda
フォロワーが少なく、いいねがもらいにくい?
記事数+ rgba(0, 127, 0, 0.3) 記事数の割合が一番高く、
他のポイントの1.1倍以上
AWS
Laravel
IoT
GoogleCloudPlatform
フォロワーが少なく、いいねがもらいにくい?
いいね--- rgba(0, 255, 255, 0.4) いいねの割合が一番低く、
他のポイントの0.4倍以下
Ubuntu 記事数、フォロワー数は比較的多いが、いいねがつきにくい?
いいね-- rgba(0, 191, 191, 0.3) いいねの割合が一番低く、
他のポイントの0.625倍以下
Ruby
PHP
Rails
Azure
R
PostgreSQL
記事数、フォロワー数は比較的多いが、いいねがつきにくい?
いいね- rgba(0, 127, 127, 0.2) いいねの割合が一番低く、
他のポイントの0.9倍以下
Swift
Kotlin
記事数、フォロワー数は比較的多いが、いいねがつきにくい?
フォロワー--- rgba(255, 255, 0, 0.4) フォロワーの割合が一番低く、
他のポイントの0.4倍以下
初心者
docker-compose
api
フォロワー数は比較的少ないが、記事は多く、いいねもついている?
フォロワー-- rgba(191, 191, 0, 0.3) フォロワーの割合が一番低く、
他のポイントの0.625倍以下
競技プログラミング
pandas
フォロワー数は比較的少ないが、記事は多く、いいねもついている?
フォロワー- rgba(127, 127, 0, 0.2) フォロワーの割合が一番低く、
他のポイントの0.9倍以下
Unity
kubernetes
gcp
Bash
Flutter
フォロワー数は比較的少ないが、記事は多く、いいねもついている?
記事数--- rgba(255, 0, 255, 0.4) 記事数の割合が一番低く、
他のポイントの0.4倍以下
- 記事数は比較的少ないが、フォロワーは多く、いいねもついている?
記事数-- rgba(191, 0, 191, 0.3) 記事数の割合が一番低く、
他のポイントの0.625倍以下
JavaScript
TensorFlow
記事数は比較的少ないが、フォロワーは多く、いいねもついている?
記事数- rgba(127, 0, 127, 0.2) 記事数の割合が一番低く、
他のポイントの0.9倍以下
- 記事数は比較的少ないが、フォロワーは多く、いいねもついている?
バランス rgba(0, 0, 0, 0.4) 上記以外
分散が近い
Docker
RaspberryPi
GoogleAppsScript
-

グラフ化

縦軸が「記事数」、横軸が「フォロワー数」、円の大きさを「いいね数」で表して、上記のグループ色でグラフ化しました。

See the Pen qiita_tag_score_v2 by j5c8k6m8 (@j5c8k6m8) on CodePen.

tooltipとかスケールとか頑張ればもう少し何とかなりますが、疲れたので。

考察等

  • グラフで見ると、「Python」と「JavaScript」が圧倒的。JavaScriptはフォロワー数やいいね数に比べると記事が不足気味
  • 記事数よりもいいね数のほうが顕著にトレンドを表しているように見える。2018/12~2019/3でいうとDeepLearning,Firebase,自然言語処理,Vue.js,機械学習,TypeScript,nuxt.js,Elmあたり
  • RUby,Rails,PHPは安定し記事数やフォロワー数に対して「いいね」はつきにくい。
  • AWSは記事数は多いが、いいね数は少ない
  • gitを含めフォロワー数が多いが、記事数といいね数が少ない安定した領域が多い←これはPythonやJavaScriptにデータが引っ張られている要因もあるかも

コード

使用した全コードはこちら

汚いので参考まで

getItems.js
const moment = require('moment')
const DATE_PIRIOD = [ '2018-12-01', '2019-03-31' ];

let request = require('request');
let fs = require("fs");

let headers = {
    'Authorization': 'Bearer 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd' // token
};

let itesm = [];
let users = [];

function getDayItems(argMoment, cnt, callback) {
  let options = {
    url: `https://qiita.com/api/v2/items?page=${cnt}&per_page=100&query=created:<${argMoment.format('YYYY-MM-DD')}`,
    headers: headers
  }
  request(options, function(error, response, body) {
    if (error) {
        return console.error('ERROR!', error);
    } else {
        let subtractDate = moment(argMoment.format('YYYY-MM-DD') + 'T09:00:00+09:00').subtract(1, 'days');
        console.log(subtractDate.format('YYYY-MM-DD'));
        let tmp = JSON.parse(body).filter( v => subtractDate.isSameOrBefore(v.created_at));
        users = users.concat(tmp.map( v => v.user.id));
        itesm = itesm.concat(tmp.map( v => { return { id: v.id, likes_count: v.likes_count, tags: v.tags, created_at: v.created_at}; }));
        if (tmp.length === 100) {
          setTimeout( () => getDayItems(argMoment, cnt + 1, callback), 3600); // 3,600秒 / 1,000回
        } else {
          callback();
        }
    }
  });
}

function getPeriod(target_moment, end_moment) {
  if (end_moment.isSameOrBefore(target_moment)) {
    getDayItems(target_moment, 1, () => getPeriod(target_moment.subtract(1, 'days'), end_moment));
  } else {
    fs.writeFile('itesm.json', JSON.stringify(itesm) , (err, data) => {});
    fs.writeFile('users.json', JSON.stringify(users.filter((x, i, self) => self.indexOf(x) === i)), (err, data) => {});
    fs.writeFile('created_at.list', itesm.map( v => v.created_at ).join('\n') , (err, data) => {});

  }
}
getPeriod(moment(DATE_PIRIOD[1]).add(1, 'days'), moment(DATE_PIRIOD[0]).add(1, 'days'));
getFollowers.js
let request = require('request');
let fs = require("fs");

let headers = {
    'Authorization': 'Bearer 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcd' // token
};

let tags = [];
let followers = [];

function getFollowers(user_id) {
  return new Promise( (resolve) => {
    let options = {
      url: `https://qiita.com/api/v2/users/${user_id}/following_tags`,
      headers: headers
    }
    request(options, function(error, response, body) {
      if (error) {
          return console.error('ERROR!', error);
      } else {
          let followers = JSON.parse(body);
          fs.writeFile(`./followers/${user_id}.json`, JSON.stringify(followers) , (err, data) => {});
          setTimeout( () => resolve(followers), 3600); // 3,600 * 1000秒 / 1,000回
      }
    });
  });
}

function getFollowersByFile(path) {
  return new Promise( (resolve) => {
    fs.readFile(path, 'utf8', function (err, text) {
      let followers = JSON.parse(text);
      resolve(followers);
    });
  });
}

(async () => {
  fs.readFile('./users.json', 'utf8', async (err, text) => {
    let user = JSON.parse(text);
    for (let i = 0; i < user.length; i++) {
      let follower_tags;
      try {
        fs.statSync(`./followers/${user[i]}.json`);
        follower_tags = await getFollowersByFile(`./followers/${user[i]}.json`);
      } catch(err) {
        follower_tags = await getFollowers(user[i]);
      }
      tags.push(follower_tags);
      console.log(tags.length);
    }
    fs.writeFile('followers.json', JSON.stringify(tags) , (err, data) => {});
  });
})()

createTags.js
let fs = require("fs");
let tag_Hash = {};
let tags = [];

fs.readFile('./items.json', 'utf8', function (err, text) {
  let items = JSON.parse(text);
  items.forEach(item => {
    item.tags.forEach( tag => {
      if (tag.name) {
        if (!tag_Hash[tag.name]) {
          tag_Hash[tag.name] = { id: tag.name, items_count: 0, followers_count: 0, likes_count: 0 };
          tags.push(tag_Hash[tag.name]);
        }
        tag_Hash[tag.name].items_count += 1;
        tag_Hash[tag.name].likes_count += item.likes_count;
      }
    });
  });

  fs.readFile('./followers.json', 'utf8', function (err, text) {
    let followers = JSON.parse(text);
    followers.forEach(follower_tags => {
      if (follower_tags.type !== 'not_found') {
        follower_tags.forEach( tag => {
            if (!tag_Hash[tag.id]) {
              tag_Hash[tag.id] = { id:tag.id, items_count: 0, followers_count: 0, likes_count: 0 };
              tags.push(tag_Hash[tag.id]);
            }
            tag_Hash[tag.id].followers_count += 1;
        });
      }
    });
    fs.writeFile('tags.json', JSON.stringify(tags) , (err, data) => {});
  });
});

editJson.js
// tags.jsonにデータが配置している前提
const OUTPUT_RANKING_NUM = 100;
const WEIGHT = { item_count: 1, followers_count: 1, likes_count: 1,};

let fs = require("fs");

const set_rank = (arr, attr, sort_flg) => {
  let target = sort_flg ? arr : arr.slice();
  target.sort( (a, b) => b[attr] - a[attr] );
  let tmp_ranking = 0;
  let tmp_score = 9999999999;
  target.forEach( (v, i) => {
    if (v[attr] < tmp_score) {
      tmp_score = v[attr];
      tmp_ranking = i + 1;
    }
    v[`${attr}_rank`] = tmp_ranking;
  })
}

const get_ranked_json = (tags, num, weight) =>{
  let total_items_count = tags.reduce( (s, v) => v.items_count + s, 0)
  let total_followers_count = tags.reduce( (s, v) => v.followers_count + s, 0)
  let total_likes_count = tags.reduce( (s, v) => v.likes_count + s, 0)
  console.log(`総タグ数: ${tags.length}, 総記事数: ${total_items_count}, 総フォロワー数: ${total_followers_count}, 総いいね数: ${total_likes_count}`);
  tags = JSON.parse(JSON.stringify(tags)); // 属性を書き換えるのでオブジェクトをコピーする

  set_rank(tags, 'items_count');
  set_rank(tags, 'followers_count');
  set_rank(tags, 'likes_count');
  tags.forEach( t => {
    t.items_point = t.items_count * 100 / total_items_count;
    t.followers_point = t.followers_count * 100 / total_followers_count;
    t.likes_point = t.likes_count * 100 / total_likes_count;
    t.score = (t.items_point * weight.item_count + t.followers_point * weight.followers_count + t.likes_point * weight.likes_count) / (weight.item_count + weight.followers_count + weight.likes_count);
    t.score_old = (t.items_point * weight.item_count + t.followers_point * weight.followers_count) / (weight.item_count + weight.followers_count);
    if (t.items_point > t.followers_point * 2.5 && t.items_point > t.likes_point * 2.5) {
      t.type = 'ITEM+++';
      t.color = 'rgba(0, 255, 0, 0.5)';
    } else if (t.followers_point > t.items_point * 2.5 && t.followers_point > t.likes_point * 2.5) {
      t.type = 'FOLLOWERS+++';
      t.color = 'rgba(0, 0, 255, 0.5)';
    } else if (t.likes_point > t.items_point * 2.5 && t.likes_point > t.followers_point * 2.5) {
      t.type = 'LIKES+++';
      t.color = 'rgba(255, 0, 0, 0.5)';
    } else if (t.items_point * 2.5 < t.followers_point && t.items_point * 2.5 < t.likes_point) {
      t.type = 'ITEM---';
      t.color = 'rgba(255, 0, 255, 0.4)';
    } else if (t.followers_point * 2.5 < t.items_point && t.followers_point * 2.5 < t.likes_point) {
      t.type = 'FOLLOWERS---';
      t.color = 'rgba(255, 255, 0, 0.4)';
    } else if (t.likes_point * 2.5 < t.items_point && t.likes_point * 2.5 < t.followers_point) {
      t.type = 'LIKES---';
      t.color = 'rgba(0, 255, 255, 0.4)';
    } else if (t.items_point > t.followers_point * 1.6 && t.items_point > t.likes_point * 1.6) {
      t.type = 'ITEM++';
      t.color = 'rgba(0, 191, 0, 0.4)';
    } else if (t.followers_point > t.items_point * 1.6 && t.followers_point > t.likes_point * 1.6) {
      t.type = 'FOLLOWERS++';
      t.color = 'rgba(0, 0, 191, 0.4)';
    } else if (t.likes_point > t.items_point * 1.6 && t.likes_point > t.followers_point * 1.6) {
      t.type = 'LIKES++';
      t.color = 'rgba(191, 0, 0, 0.4)';
    } else if (t.items_point * 1.6 < t.followers_point && t.items_point * 1.6 < t.likes_point) {
      t.type = 'ITEM--';
      t.color = 'rgba(191, 0, 191, 0.3)';
    } else if (t.followers_point * 1.6 < t.items_point && t.followers_point * 1.6 < t.likes_point) {
      t.type = 'FOLLOWERS--';
      t.color = 'rgba(191, 191, 0, 0.3)';
    } else if (t.likes_point * 1.6 < t.items_point && t.likes_point * 1.6 < t.followers_point) {
      t.type = 'LIKES--';
      t.color = 'rgba(0, 191, 191, 0.3)';
    } else if (t.items_point > t.followers_point * 1.1 && t.items_point > t.likes_point * 1.1) {
      t.type = 'ITEM+';
      t.color = 'rgba(0, 127, 0, 0.3)';
    } else if (t.followers_point > t.items_point * 1.1 && t.followers_point > t.likes_point * 1.1) {
      t.type = 'FOLLOWERS+';
      t.color = 'rgba(0, 0, 127, 0.3)';
    } else if (t.likes_point > t.items_point * 1.1 && t.likes_point > t.followers_point * 1.1) {
      t.type = 'LIKES+';
      t.color = 'rgba(127, 0, 0, 0.3)';
    } else if (t.items_point * 1.1 < t.followers_point && t.items_point * 1.1 < t.likes_point) {
      t.type = 'ITEM-';
      t.color = 'rgba(127, 0, 127, 0.2)';
    } else if (t.followers_point * 1.1 < t.items_point && t.followers_point * 1.1 < t.likes_point) {
      t.type = 'FOLLOWERS-';
      t.color = 'rgba(127, 127, 0, 0.2)';
    } else if (t.likes_point * 1.1 < t.items_point && t.likes_point * 1.1 < t.followers_point) {
      t.type = 'LIKES-';
      t.color = 'rgba(0, 127, 127, 0.2)';
    } else {
      t.type = 'NORMAL';
      t.color = 'rgba(0, 0, 0, 0.3)';
    }
    t.diff = t.followers_point - t.items_point;
  })
  set_rank(tags, 'score_old');
  set_rank(tags, 'score', true);
  return tags.slice(0, num);
}

const to_chart_data = v => {
  return { label: v.id, data: [ { x: v.followers_count, y: v.items_count, r: 6 + (8 * v.likes_point) } ], backgroundColor: v.color }
};

fs.readFile('./tags.json', 'utf8', function (err, text) {
  let tags = JSON.parse(text);
  tags = get_ranked_json(tags, OUTPUT_RANKING_NUM, WEIGHT);

  let str = '"タグ名",評価値順位,フォロワー数順位,記事数順位,いいね数順位,評価値,フォロワー数,記事数,いいね数,タイプ\n';
  str += tags.map( v => `"${v.id}",${v.score_rank},${v.followers_count_rank},${v.items_count_rank},${v.likes_count_rank},${v.score},${v.followers_count},${v.items_count},${v.likes_count},${v.type}`).join('\n')
  fs.writeFile(`list.csv`, str , (err, data) => {});
  fs.writeFile(`chart.json`, JSON.stringify(tags.filter( v => v.score_rank <= OUTPUT_RANKING_NUM ).map(to_chart_data)) , (err, data) => {});

  // 最後ソートしてから
  tags.sort( (a, b) => b.score_old - a.score_old );
  str = '"タグ名",評価値順位,フォロワー数順位,記事数順位,評価値,フォロワー数,記事数,評価値差分,\n';
  str += tags.map( v => `"${v.id}",${v.score_old_rank},${v.followers_count_rank},${v.items_count_rank},${v.score_old},${v.followers_count},${v.items_count},${v.diff}`).join('\n')
  fs.writeFile(`list_old.csv`, str , (err, data) => {});

});

さいごに

意外と感覚的に正しそうな値が出たので満足したが、2018/12~2019/3以外に、時系列で同様の分析をしても新たな発見があるかも。(リクエストがあれば。)

これで、関連記事に同じ観点の記事が出たら負け。

4
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3