前々からフリーランス案件の言語別単価を比較&集計してみたかったので実際に調査してみました
フリーランス案件の情報は下記サイトを元に集計しました
各言語のページに集計情報があったのでそれを元にしています
レバテックフリーランス
https://freelance.levtech.jp
※2020年11月21日時点のデータです
Cloud.csv
created_at,skill,count,avg_price,max_price,min_price
20201121,OpenShift,5,62,65,60
20201121,Amazon VPC,1,70,70,70
20201121,Google Cloud Platform,55,80,105,53
20201121,Dynamics CRM,1,65,65,65
20201121,Amazon S3,2,80,85,75
20201121,Amazon EC2,2,74,85,64
20201121,AWS,1926,76,135,20
20201121,Google App Engine,7,77,95,60
20201121,Amazon SimpleDB,1,80,80,80
20201121,Force.com,2,70,70,70
20201121,Office 365,9,56,65,40
20201121,Microsoft Azure,141,67,90,50
20201121,OpenStack,21,64,80,45
20201121,Heroku,29,75,102,55
DB.csv
created_at,skill,count,avg_price,max_price,min_price
20201121,Kyoto Tycoon,1,75,75,75
20201121,SQLite,20,72,90,55
20201121,MySQL,1465,75,125,35
20201121,Symfoware Server,4,60,65,55
20201121,Cassandra,14,62,80,45
20201121,PostgreSQL,487,71,135,35
20201121,Riak,5,63,100,45
20201121,Bigtable,3,86,95,80
20201121,SQL Server,375,65,95,35
20201121,Redis,296,78,105,39
20201121,Hbase,5,68,75,60
20201121,Oracle,971,66,115,25
20201121,Sybase,6,75,85,65
20201121,IMS,3,58,64,55
20201121,Access,88,60,145,40
20201121,DB2,79,64,95,35
FrameWork.csv
created_at,skill,count,avg_price,max_price,min_price
20201121,Pyramid,12,77,105,65
20201121,Rails,237,81,115,45
20201121,MyBatis,61,71,85,55
20201121,Node.js,256,77,125,45
20201121,Backbone.js,77,76,115,39
20201121,Knockout.js,4,72,90,55
20201121,AngularJS,152,74,105,47
20201121,Laravel,343,73,125,40
20201121,JUnit,80,73,125,50
20201121,Wicket,3,82,95,70
20201121,Django,89,83,115,55
20201121,Padrino,2,82,85,80
20201121,iBATIS,14,67,80,55
20201121,Silex,4,76,80,75
20201121,FuelPHP,101,76,115,50
20201121,MVC,69,68,95,37
20201121,CodeIgniter,39,74,105,45
20201121,Liferay,1,70,70,70
20201121,React,378,77,115,40
20201121,Spark,19,82,95,55
20201121,PhoneGap,3,86,95,80
20201121,JSF,18,64,75,55
20201121,jQuery,354,71,95,35
20201121,Seasar2,32,70,95,49
20201121,Spring,362,71,115,45
20201121,Bottle,1,75,75,75
20201121,Catalyst,26,64,72,55
20201121,intra-mart,14,70,135,50
20201121,SAStruts,16,71,95,57
20201121,Flask,25,82,125,65
20201121,Sinatra,6,78,85,75
20201121,Struts,129,67,95,45
20201121,Symfony,55,74,95,55
20201121,CakePHP,149,71,95,50
Language.csv
created_at,skill,count,avg_price,max_price,min_price
20201121,PHP,1560,72,145,35
20201121,CSS,650,70,125,35
20201121,C言語,269,68,115,35
20201121,UML,7,70,85,50
20201121,C++,374,72,125,45
20201121,C#.NET,147,62,80,32
20201121,Transact-SQL,6,65,75,55
20201121,Kotlin,270,83,125,45
20201121,VB,83,62,85,40
20201121,HTML5,305,72,115,35
20201121,VC,8,61,66,50
20201121,C#,706,68,115,35
20201121,Apex,49,79,135,55
20201121,VBA,165,60,145,30
20201121,ASP.NET,161,65,95,48
20201121,Go,361,81,125,39
20201121,PL/SQL,146,63,85,45
20201121,COBOL,81,61,95,37
20201121,LESS,9,74,115,55
20201121,Swift,407,81,125,50
20201121,VC++,30,65,90,52
20201121,HTML,674,69,125,35
20201121,CSS3,209,75,115,35
20201121,Java,2484,70,145,25
20201121,JSP,54,68,105,55
20201121,Sass,55,71,115,45
20201121,SQL,881,65,145,33
20201121,VBScript,44,62,75,45
20201121,Objective-C,247,76,115,40
20201121,CoffeeScript,16,81,95,65
20201121,JavaScript,1749,72,125,20
20201121,Lua,6,73,80,65
20201121,R言語,19,78,95,65
20201121,Smalltalk,2,75,80,70
20201121,Scala,117,83,115,55
20201121,Perl,108,73,110,50
20201121,Shell,193,64,95,45
20201121,SAS,12,61,75,50
20201121,Ruby,652,80,125,39
20201121,ABAP,12,67,80,55
20201121,Python,669,78,145,32
20201121,VB.NET,284,62,85,40
OS.csv
created_at,skill,count,avg_price,max_price,min_price
20201121,Windows,998,63,135,25
20201121,Red Hat,92,66,95,40
20201121,Solaris,37,61,80,40
20201121,AIX,77,63,90,52
20201121,Ubuntu,39,75,90,45
20201121,Unix,236,69,100,40
20201121,AS/400,1,65,65,65
20201121,FreeBSD,3,70,75,62
20201121,HP-UX,21,62,75,55
20201121,Windows Server,387,62,100,33
20201121,Android,563,78,125,35
20201121,Linux,2266,69,135,30
グラフ画像出力ソースがこちら
print_graph.py
import datetime
import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
"""
共通変数・定数設定
"""
DATA_PATH = 'data'
now = datetime.datetime.today()
CATEGORIES = {
'Language',
'FrameWork',
'DB',
'OS',
'Cloud'
}
"""
メイン処理
"""
def main() -> None:
make_date = now.strftime("%Y%m%d")
# ディレクトリ作成
os.makedirs(DATA_PATH + '/graphs/' + make_date, exist_ok=True)
price_graph(make_date)
count_graph(make_date)
mix_graph(make_date)
"""
単価グラフ作成
"""
def price_graph(make_date: str) -> None:
for category_key in CATEGORIES:
df = pd.read_csv(DATA_PATH + '/levtech/' + category_key + '.csv')
df = df.sort_values(by=['avg_price'], ascending=False)
labels = df['skill'].str.replace('[ぁ-んァ-ン一-龥]+', '', regex=True) # 日本語削除
y_list1 = df['avg_price']
fig = plt.figure(figsize=(14, 7))
ax1 = fig.add_subplot(1, 1, 1)
ax1.bar(labels, y_list1, color='tab:blue')
ax1.set_ylabel('price')
ax1.set_title(category_key)
# X軸を縦書き表示
ax1.set_xticklabels(labels, rotation=90)
# 棒グラフに数値追記
for x, y in zip(labels, y_list1):
ax1.text(x, y, y, ha='center', va='bottom')
# plt.show()
fig.savefig(DATA_PATH + '/graphs/' + make_date + '/levtech-' + category_key + '-price.png', bbox_inches='tight', format='png', dpi=300)
"""
案件数グラフ作成
"""
def count_graph(make_date: str) -> None:
for category_key in CATEGORIES:
df = pd.read_csv(DATA_PATH + '/levtech/' + category_key + '.csv')
df = df.sort_values(by=['count'], ascending=False)
labels = df['skill'].str.replace('[ぁ-んァ-ン一-龥]+', '', regex=True) # 日本語削除
y_list1 = df['count']
fig = plt.figure(figsize=(14, 7))
ax1 = fig.add_subplot(1, 1, 1)
ax1.bar(labels, y_list1, color='tab:orange')
ax1.set_ylabel('count')
ax1.set_title(category_key)
# X軸を縦書き表示
ax1.set_xticklabels(labels, rotation=90)
# 棒グラフに数値追記
for x, y in zip(labels, y_list1):
ax1.text(x, y, y, ha='center', va='bottom', fontsize='small')
# plt.show()
fig.savefig(DATA_PATH + '/graphs/' + make_date + '/levtech-' + category_key + '-count.png', bbox_inches='tight', format='png', dpi=300)
"""
単価&案件数グラフ作成
"""
def mix_graph(make_date: str) -> None:
for category_key in CATEGORIES:
df = pd.read_csv(DATA_PATH + '/levtech/' + category_key + '.csv')
df = df.sort_values(by=['avg_price'], ascending=False)
labels = df['skill'].str.replace('[ぁ-んァ-ン一-龥]+', '', regex=True) # 日本語削除
y_list1 = df['avg_price']
y_list2 = df['count']
fig = plt.figure(figsize=(14, 7))
left = np.arange(len(labels))
width = 0.3
ax1 = fig.add_subplot(1, 1, 1)
ax1.bar(labels, y_list1, width=width, color='tab:blue', label='price')
ax1.set_ylabel('price')
ax1.set_title(category_key)
ax2 = ax1.twinx()
ax2.bar(left + width, y_list2, width=width, color='tab:orange', label='count')
ax2.set_ylabel('count')
# X軸を縦書き表示
ax1.set_xticklabels(labels, rotation=90)
# 棒グラフに数値追記
for x, y in zip(labels, y_list1):
ax1.text(x, y, y, ha='center', va='bottom')
for x, y in zip(left + width, y_list2):
ax2.text(x, y, y, ha='center', va='bottom', fontsize='small')
# 凡例を出力
handler1, label1 = ax1.get_legend_handles_labels()
handler2, label2 = ax2.get_legend_handles_labels()
ax1.legend(handler1 + handler2, label1 + label2)
# plt.show()
fig.savefig(DATA_PATH + '/graphs/' + make_date + '/levtech-' + category_key + '-mix.png', bbox_inches='tight', format='png', dpi=300)
if __name__ == '__main__':
main()
実際のグラフ
- priceが平均単価(万円)
- countが案件数です
- 単価と案件数が混ざったグラフは、単価が高い順です
言語
単価別
案件数別
単価と案件数mix
トップはKotlinですね。今Androidエンジニアが不足していると聞くので納得。
web系なら案件数と単価で見るとRuby、Python、goがコスパ良さそうですね。
Javaはとりあえず単価が高いイメージがあったんですが、PHPの方が高いというのは意外、、、需要が高すぎるんでしょうか?
次にフレームワーク
単価別
案件数別
単価と案件数mix
トップはPhoneGapですね。自分は初めて聞いたんですが、Nitobiが開発,公開しているクロスプラットフォーム・モバイルアプリケーションの開発フレームワークらしいです。
web系だとこれまたDjangoやRailsがコスパ良さそうですね。Reactはwebなりアプリ開発に使われているので案件数も単価も良さげ。Vueはサイト元に情報が無かったです。。
DB
単価別
案件数別
単価と案件数mix
トップはBigtableです。Bigqueryはよく聞くんですが、違いはBigqueryより高速に動く大規模DBみたいな感じらしいです。
DBに関してはコスパで言うとMySQL覚えておけば間違い無いですね。Oracle、SQLServerは意外と低い。どうして、、、
Cloud
単価別
案件数別
単価と案件数mix
単価トップはGCPですね!案件数でいくとAWSが圧倒的!とりあえずAWSは最低限覚えた方が良さそうですね
需要が高くなりすぎると単価が安くなる傾向が見られるので、これからのことを考えるとGCPも覚えた方がいいかも?
Azureは案件数も単価数も微妙ですね
感想
なかなか面白い結果になりました!
これからweb系やるならPythonが伸びしろあるかもです。実際触ってみて、環境構築が手軽。ライブラリが豊富。特にCSV→グラフ作成がこんなに簡単にできるのには感動しました!
わざわざhtmlやjsのライブラリを使ってゴニョゴニョするよりバックエンドでさくっと作って画像化出来るのがとてもイイですね〜
今回はあくまで案件サイトの一つを調査した結果なので参考程度にしていただけると!
VueやGraphql、Rustの情報が載っていなかったのでそこらへんも気になるところですね〜