はじめに
どのプログラミング言語を勉強したらいいか?人気な言語はどれ?気になる人もたくさんいるでしょう。ランキングしようとしても色んな基準があって一概と答えることはできないが、ここではQiitaでの記事数とフォロワー数でランキングを纏めてみたいと思います。参考になれば幸いです。
纏める方法はQiitaAPIを通じてデータを取得して扱うことです。主にPythonを使いますが、Flutterを使ってスマホで表示するアプリも作ってみたので、ここでもコードを載せて説明します。
結果発表
扱う対象について
ここで扱うのは言語の名前であるQiitaでのタグです。全部65言語あります。
勿論実際にもっとたくさん言語があるはずですが、ここでQiitaで記事数が50以上だけ扱うので、あまり誰も知らないマイナー言語は含まれません。(私が使うIDL言語も記事数9しかないので入れていません。ALGOLやAdaも)
できるだけたくさんの言語を入れようとしていますが、もしまだどこかの人気言語を見落としていたら指摘して頂ければ追加します。
ここで扱うのはプログラミング言語だけなので、SQL、HTML、CSS、LaTeXなどは対象外です。
SASやCoqなど独特な言語を使うソフトウェアはプログラミング言語リストに入ることもあるようですが、厳密にはプログラミング言語の名前ではなくソフトウェアの名前なので対象外です。
VBAはVB(Visual Basic)言語の用途で言語自体を差すのではないので対象外ですが、実際にVBAタグの数が圧倒的にVBやVB.netより多いので、VBの人気はVBAタグで考慮した方がいいかもしれません。
一文字の名前の言語はC言語、D言語、R言語がありますが、ここではCとRはそのままタグの名前として定着していますが、D言語はdlangというタグが使われています。clangというタグもありますが、これはC言語のことではなく、別の意味なので紛らわしい気もします。
Mind、なでしこ、プロデルという日本語プログラミング言語も含まれます。
全部の言語のタグ纏め
以下の表は2024年1月20日時点でQiitaAPIから取得したデータから纏めたもの。名前の順で並んでいます。後ろにある括弧はこの65の言語の中での順位。
言語 | 記事数 | フォロワー数 |
---|---|---|
ActionScript | 261 (46位) | 235 (40位) |
AppleScript | 489 (38位) | 168 (46位) |
assembly | 154 (55位) | 67 (52位) |
AWK | 560 (34位) | 287 (36位) |
BASIC | 200 (49位) | 9 (64位) |
brainfuck | 75 (63位) | 17 (61位) |
C | 5250 (12位) | 34130 (8位) |
C# | 16168 (7位) | 49961 (6位) |
C++ | 11123 (10位) | 40338 (7位) |
Carbon | 119 (59位) | 7 (65位) |
Clojure | 691 (27位) | 563 (26位) |
cobol | 153 (56位) | 71 (51位) |
CoffeeScript | 967 (23位) | 17071 (12位) |
Crystal | 296 (44位) | 207 (43位) |
Dart | 2844 (18位) | 876 (23位) |
Delphi | 686 (28位) | 229 (41位) |
dlang | 511 (37位) | 228 (42位) |
ECMAScript | 560 (35位) | 282 (37位) |
Elixir | 4469 (14位) | 1301 (21位) |
Elm | 674 (29位) | 565 (25位) |
Erlang | 564 (33位) | 430 (29位) |
F# | 399 (40位) | 337 (33位) |
Forth | 80 (62位) | 22 (59位) |
Fortran | 661 (30位) | 332 (34位) |
GLSL | 602 (32位) | 436 (28位) |
Go | 12869 (9位) | 8217 (17位) |
Groovy | 608 (31位) | 267 (38位) |
Haskell | 2251 (19位) | 14395 (14位) |
Haxe | 178 (52位) | 190 (45位) |
Java | 23712 (5位) | 88248 (3位) |
JavaScript | 54947 (2位) | 147065 (2位) |
JScript | 177 (53位) | 54 (54位) |
Julia | 1477 (21位) | 1061 (22位) |
Kotlin | 7086 (11位) | 3326 (19位) |
lisp | 429 (39位) | 400 (30位) |
Lua | 729 (26位) | 376 (32位) |
MATLAB | 1274 (22位) | 735 (24位) |
mind | 175 (54位) | 16 (62位) |
Nim | 382 (42位) | 378 (31位) |
Objective-C | 4067 (16位) | 23653 (10位) |
OCaml | 199 (50位) | 257 (39位) |
Pascal | 232 (48位) | 20 (60位) |
Perl | 1832 (20位) | 18229 (11位) |
PHP | 28955 (4位) | 81755 (4位) |
Prolog | 385 (41位) | 124 (49位) |
purescript | 263 (45位) | 164 (47位) |
Python | 78028 (1位) | 167011 (1位) |
Q# | 58 (64位) | 48 (56位) |
R | 4714 (13位) | 2547 (20位) |
Ruby | 40765 (3位) | 67430 (5位) |
Rust | 4281 (15位) | 3639 (18位) |
Scala | 3353 (17位) | 15669 (13位) |
Scheme | 247 (47位) | 11966 (15位) |
Scratch | 381 (43位) | 158 (48位) |
Smalltalk | 144 (57位) | 62 (53位) |
solidity | 917 (24位) | 330 (35位) |
SuperCollider | 52 (65位) | 53 (55位) |
Swift | 21976 (6位) | 10768 (16位) |
Tcl | 97 (61位) | 40 (57位) |
TypeScript | 13663 (8位) | 27267 (9位) |
VB | 101 (60位) | 88 (50位) |
VB.Net | 734 (25位) | 462 (27位) |
VBScript | 554 (36位) | 199 (44位) |
なでしこ | 198 (51位) | 25 (58位) |
プロデル | 121 (58位) | 14 (63位) |
記事数ランキング
Qiitaで最も記事数が多い言語トップ40を棒グラフに書いて纏めます。
やはり一番人気なのはPythonで次はJavaScriptですね。これは記事数だけでなく、フォロワー数を見ても同じ結果です。
フォロワー数ランキング
フォロワー数で並べてまた棒グラフを見たらこうなります。
記事数と比べたら大体同じような傾向ですが、違うところも多いです。Rubyは記事数は3番なのに、フォロワーは5番となっています。逆にPerlやCoffeeScriptなどはフォロワー数のわりに記事数は少ない。更にSchemeはフォロワー数だけすごく多いが、記事数ランキングに入らないのです。
記事数とフォロワー数の分布図
記事数とフォロワーの関係を可視化するために分布図も描きます。ただし多すぎないようにここでは記事数25番までだけ表示します。
Pythonによる実装
以上QiitaAPIに接続してデータを取ってグラフに書いたのは全部、一番人気と言われるPythonです。
Pythonを使うとどの作業も簡単にできてしまって本当に便利ですね。人気になるのも当然な結果でしょう。
ここでは今回使ったコードも載せます。
データ取得
まずデータを取得して.csv
に保存するコードです。requests
とpandas
を使ったら簡単にできます。
import requests
import pandas as pd
lis_df = []
for i in range(1,51):
req = requests.get('https://qiita.com/api/v2/tags?page=%d&per_page=100&sort=count'%i)
lis_df.append(pd.DataFrame(req.json())[['id','items_count','followers_count']])
pd.concat(lis_df,ignore_index=True).set_index('id').to_csv('qiita_tag.csv')
ここで得られるのは最も記事数が多い5000のタグです。その中に今回の対象であるプログラミング言語の前であるタグが含まれます。
棒グラフと分布図
データを手に入れた後、次は纏めてmatplotlib
でグラフを描きます。
import pandas as pd
import matplotlib.pyplot as plt
# 扱う言語のリスト
gengo_lis = 'ActionScript AppleScript assembly AWK BASIC brainfuck C C# C++ Carbon Clojure cobol CoffeeScript Crystal Dart Delphi dlang ECMAScript Elixir Elm Erlang F# Forth Fortran GLSL Go Groovy Haskell Haxe Java JavaScript JScript Julia Kotlin lisp Lua MATLAB mind Nim Objective-C OCaml Pascal Perl PHP Prolog purescript Python Q# R Ruby Rust Scala Scheme Scratch Smalltalk solidity SuperCollider Swift Tcl TypeScript VB VB.Net VBScript なでしこ プロデル'.split(' ')
# 言語の名前であるタグだけ抽出する
df = pd.read_csv('qiita_tag.csv',index_col='id').loc[gengo_lis]
# フォロー数の棒グラフ
y = range(40)
plt.figure(figsize=[6,7.5],dpi=100)
ax = plt.axes(ylim=[min(y)-0.5,max(y)+0.5])
df.sort_values('followers_count',inplace=True)
plt.barh(y,df['followers_count'][-40:],color='#AAEE44',ec='k')
plt.yticks(y,['%s: %6s'%x for x in df['followers_count'][-40:].items()])
plt.title('フォロー数',family='MS Gothic')
plt.semilogx()
plt.tight_layout()
plt.savefig('folrank.png')
# 記事数の棒グラフ
plt.figure(figsize=[6,7.5],dpi=100)
ax = plt.axes(ylim=[min(y)-0.5,max(y)+0.5])
df.sort_values('items_count',inplace=True)
plt.barh(y,df['items_count'][-40:],color='#EEAA44',ec='k')
plt.yticks(y,['%s: %6s'%x for x in df['items_count'][-40:].items()])
plt.title('記事数',family='MS Gothic')
plt.semilogx()
plt.tight_layout()
plt.savefig('kijirank.png')
# 記事数とフォロワー数を比較する散布図
plt.figure(figsize=[6,6],dpi=100)
plt.xlabel('記事数',family='MS Gothic')
plt.ylabel('フォロー数',family='MS Gothic')
plt.scatter(df['items_count'][-25:],df['followers_count'][-25:],s=6,fc='r')
for gengo in df.index[-25:]:
plt.text(df['items_count'][gengo],df['followers_count'][gengo],gengo,ha='right',va='top',family='MS Gothic',size=9)
plt.loglog()
plt.grid(ls=':',which='both')
plt.tight_layout()
plt.savefig('kiji-fol.png')
plt.close()
なお、ランキングの順位はこう書いて得られます。
df['items_count_rank'] = (-df['items_count']).argsort().argsort()+1
df['followers_count_rank'] = (-df['followers_count']).argsort().argsort()+1
Flutterによる実装
できたもの
最近Flutterを勉強し始めて随分と気に入ったので、この実装もFlutterで何かしたくてこんなものを作ることになりました。
まずできたアプリを.apk
ファイルにデプロイしてスマホに入れてインストールして起動したらまずは空っぽですが、「データをロードする」ボタンを押したらQiitaAPIからタグのデータを読み込んで纏めて並べてこういう表が出てきます。スライドして下の方も見られます。
このアプリは3タブに分けられて、次のタブを押したら記事数の順番で並んでいる棒グラフになります。
そしてフォロワー数の順番で並んでいる棒グラフ。
一度ロードしたらデータは保存されるので、閉じて再びアプリを起動してもデータはそのままで、もう一度ロードする必要はないが、時間が経ってまた新しいデータに更新したい場合またボタンを押します。
実装のコード
ここではFlutterやDartなどの基本を省略します。コードの中で色々解説を書きます。
使うパッケージ
今回の実装で必要なのはこの2つのパッケージです。
http
はQiitaAPIに接続してデータを取得するためであり、shared_preferences
は取得したデータを保存するためです。
AndroidManifest.xml
Androidでhttp
パッケージが使えるようにするにこの部分を追加する必要があります。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
pubspec.yml
今回使う2つのパッケージをpubspec.yml
に追加します。
shared_preferences: ^2.2.2
http: ^1.2.0
main.dart
コードは分けずに全部ただ一つのファイルに纏めているので長いです。分けてもいいが、面倒くなるのでこのままでいい。
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(const QiiApp());
}
class QiiApp extends StatelessWidget {
const QiiApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const DefaultTabController(length: 3, child: QiiPage()),
);
}
}
class QiiPage extends StatefulWidget {
const QiiPage({super.key});
@override
State<QiiPage> createState() => _QiiPageState();
}
class _QiiPageState extends State<QiiPage> {
// 扱うプログラミング言語の名前のリスト
List gengoLis =
'ActionScript AppleScript assembly AWK BASIC brainfuck C C# C++ Carbon Clojure cobol CoffeeScript Crystal Dart Delphi dlang ECMAScript Elixir Elm Erlang F# Forth Fortran GLSL Go Groovy Haskell Haxe Java JavaScript JScript Julia Kotlin lisp Lua MATLAB mind Nim Objective-C OCaml Pascal Perl PHP Prolog purescript Python Q# R Ruby Rust Scala Scheme Scratch Smalltalk solidity SuperCollider Swift Tcl TypeScript VB VB.Net VBScript なでしこ プロデル'
.split(' ');
// 必要なウィジェットのリスト変数を宣言しておく
List<TableRow> tableRowLis = [];
List<Row> kijiRankBar = [];
List<Stack> folRankBar = [];
// タグのデータを並べてウィジェットに入れる
void setQdata(qdata) {
// 言語リストに含まれるものだけ取得する
List qTagLis1 = qdata.where((q) => gengoLis.contains(q['id'])).toList();
// リストをコピーする
List qTagLis2 = [...qTagLis1];
List qTagLis3 = [...qTagLis1];
// 名前で並び替える
qTagLis1
.sort((a, b) => a['id'].toUpperCase().compareTo(b['id'].toUpperCase()));
// 記事数で並び替える
qTagLis2.sort((a, b) => b['n_kiji'].compareTo(a['n_kiji']));
// フォロワー数で並び替える数で並び替える
qTagLis3.sort((a, b) => b['n_fol'].compareTo(a['n_fol']));
int nKijiMax = 0; // 記事数の最大値
int nFolMax = 0; // フォロワー数の最大値
TextStyle style =
const TextStyle(fontWeight: FontWeight.bold, fontSize: 18);
// 全体のデータを表示する表の行
tableRowLis = [
// ヘッダの行
TableRow(children: <Widget>[
TableCell(
child: Container(
padding: const EdgeInsets.all(3),
alignment: Alignment.center,
child: Text('言語', style: style),
),
),
TableCell(
child: Container(
padding: const EdgeInsets.all(3),
alignment: Alignment.center,
child: Text('記事', style: style),
),
),
TableCell(
child: Container(
padding: const EdgeInsets.all(3),
alignment: Alignment.center,
child: Text('フォロワー', style: style),
),
),
])
];
// 表に行を入れていく
for (Map q in qTagLis1) {
// 最大値の更新
if (q['n_kiji'] > nKijiMax) nKijiMax = q['n_kiji'];
if (q['n_fol'] > nFolMax) nFolMax = q['n_fol'];
tableRowLis.add(TableRow(
children: <Widget>[
// 言語の名前
TableCell(
child: Container(
padding: const EdgeInsets.fromLTRB(10, 3, 10, 3),
child: Text('${q['id']}'),
),
),
// 記事数
TableCell(
child: Container(
padding: const EdgeInsets.fromLTRB(10, 3, 10, 3),
alignment: Alignment.centerRight,
child: Text('${q['n_kiji']}'),
),
),
// フォロワー数
TableCell(
child: Container(
padding: const EdgeInsets.fromLTRB(10, 3, 10, 3),
alignment: Alignment.centerRight,
child: Text('${q['n_fol']}'),
),
)
],
));
}
// 記事数順で表す行のリスト
kijiRankBar = [];
for (Map q in qTagLis2) {
kijiRankBar.add(Row(
children: [
Container(
// 言語の名前を書く左の部分
color: const Color(0xFFDDDDEE),
width: 100,
height: 28,
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Text(q['id']),
),
),
Flexible(
// 記事数によって長くなる棒
child: FractionallySizedBox(
widthFactor: q['n_kiji'] / nKijiMax,
child: Container(
color: const Color(0xFFEEAA44),
height: 26,
),
),
),
Container(
// 棒の右側に記事数
padding: const EdgeInsets.all(3.0),
child: Text('${q['n_kiji']}'),
),
],
));
}
// フォロワー数順で表す行のリスト
folRankBar = [];
for (Map q in qTagLis3) {
folRankBar.add(Stack(
children: [
Container(
// 棒の後ろの灰色
color: const Color(0xFFDDDDEE),
height: 26,
),
Container(
// フォロワー数によって長くなる棒
color: const Color(0xFFAAEE44),
width: MediaQuery.of(context).size.width * q['n_fol'] / nFolMax,
height: 26,
),
SizedBox(
// 言語の名前とフォロワー数
height: 28,
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Text('${q['id']} (${q['n_fol']})'),
),
),
],
));
}
}
// QiitaAPIからデータを取得する関数
void loadQiitaTag() async {
List qdata = []; // タグのデータわ収めるリスト
try {
for (int i = 1; i < 51; i++) {
// QiitaAPIにアクセス
var response = await http.get(Uri.parse(
'https://qiita.com/api/v2/tags?page=$i&per_page=100&sort=count'));
for (Map q in jsonDecode(response.body)) {
// 読み込まれたデータをリストに収めていく
qdata.add({
'id': q['id'],
'n_kiji': q['items_count'],
'n_fol': q['followers_count'],
});
}
}
// shared_preferencesを起動する
SharedPreferences prefs = await SharedPreferences.getInstance();
// データを保存する
await prefs.setString('qdata', jsonEncode(qdata));
// 表示のために配置する
setState(() {
setQdata(qdata);
});
} catch (e) {
// 何かエラーが出る場合そのエラーメッセージを表示する
setState(() {
tableRowLis = [
TableRow(children: <Widget>[Text('$e')])
];
});
}
}
// shared_preferencesで保存されたデータを読み込んで配置する
void readQdata() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
setQdata(jsonDecode(prefs.getString('qdata') ?? '[]'));
});
}
// アプリを起動した時に実行する関数
@override
void initState() {
super.initState();
readQdata();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: const Color(0xFF88FFCC),
title: const TabBar(
// 上のメニューの部分
isScrollable: true,
indicatorColor: Color(0xFFCC9966),
tabs: [
Tab(text: '全体'),
Tab(text: '記事数順'),
Tab(text: 'フォロワー数順'),
],
labelStyle: TextStyle(fontSize: 20),
)),
body: TabBarView(children: [
// 全体のデータを表すタブ
ListView(
children: [
// 押したらQiitaAPIに接続してデータを取得するボタン
ElevatedButton(
onPressed: loadQiitaTag,
child: const Text(
'データをロードする',
style: TextStyle(fontSize: 20),
),
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Table(
border: TableBorder.all(),
children: tableRowLis,
),
)
],
),
// 記事数のタブ
ListView(
children: kijiRankBar,
),
// フォロワー数のタブ
ListView(
children: folRankBar,
),
]),
);
}
}
参考になった記事
- Flutterでshared_preferencesを使う
- DartでListをソートする方法
- Flutterでタブ画面を作る。
- [Flutter] TabBarとTabBarViewを勉強しよう。
- FlutterでちょっとイケてるTabを書く
- 【Flutter】AppBarを使わずにTabBarを使う
- DartのListやMapのClone(Deep Copy)
- 【Dart】自作クラスのリストに関するあれこれ
- 【Flutter】TableのWidgetに枠線(border)を付けたい
- 【Flutterレイアウト】Flex、Row、Column、Wrap、Stackについて
- FlutterでHTTPリクエストやってみる。
他にプログラミング言語ランキング関連の記事
ランキングの基準はそれぞれ色々違って、時間によっても変わっていくので、この記事以外にも色んな基準と色んな時期に書いた記事を読んで比べて参考にしてみましょう。
以下Qiitaで見つけた他のランキング関連の記事:
- GitHubから言語ランキング作ってみた(2013/07/26)
- 人気プログラミング言語ランキング(2015年)
- プログラミング言語ランキングより:2016年 動向を見守るべき言語は Elixir、Julia、Rust、Swift、TypeScript
- GitHub からみたプログラミング言語の動向(半年変化をアップデート)(2016年)
- 初心者がこれから学ぶべき言語を目的別にまとめてみた(2016年)
- プログラミング言語の人気(2017年)
- 言語選定とかしてみる(2018年)
- 2019年にお勧めのプログラミング言語
- 2019年にわざわざ学ばなくてもいいプログラミング言語
- 全ての開発者が学ぶべき5つの言語(2019年)
- プログラム言語ランキング(2019年)
- QiitaAPIで各プログラミング言語のタグの記事とフォロワーの数を調べて纏めたりする(pythonとrubyを使う)(2019年)
- Qiitaに掲載されているプログラミング言語別の記事数を調べてみた(2020年)
- 8月のプログラミング言語ランキング:データ抽出と人工知能言語の台頭!(2021年)
- 2022年第一四半期 プログラミング言語ランキング
- おしゃれなプログラミング言語ランキング(2023年)
- 実際なんの言語が市場で需要が高いんだろう?と思って調べてみました(2023年)
- 「実際に仕事で使われているプログラミング言語」ランキング(2023年)
- アドベントカレンダーでプログラミング言語ランキングしてみた(2023年)