IT上場企業の平均年収を再分析してみた

## はじめに

よくビジネス記事などで、平均給与ランキングという記事があるが、
いささか平均というものは魔術でゴニョゴニョされることが多いので、
こういう指標だとどうなの？というのをチュートリアル的に書いてみたいと思う。

**基本的にこの解析は雑** なので、あまり結果を鵜呑みにしない方が良い。

## 余談

この記事は、年始にデスクトップを整理していたら出てきて、削除しようと思ったけどいちおう結論まで出ていたから供養しようと投稿するもので、真面目に企業を査定しようとするものではありません。

## アイデア

まず、平均年齢が上がれば年収が増えるという直感がある。
一般に同じ会社の中から適当に社員をサンプリングしてきたとき、年齢が高い方が身に付ける能力や技能は高く、さらには役職に付く可能性も高く、同時に年収も高い傾向にある、という経験則からである。
また、従業員数が増えれば役職の数も増えると考えられ、それらが平均年収に寄与するのかどうか、ということも知りたい。

そこで、平均年齢、従業員数をそれぞれ説明変数とし、平均年収を予測するモデルを構築する。

## 必要なモジュールのインポート

pip や anaconda で簡単に環境づくりできる時代なので、各モジュールのインストールは省略する。
ここでは、`numpy`、`pandas`、`sklearn`、`xgboost` をインストールする必要がある（`xgboost`だけ少し複雑かもしれない）。

```python
import numpy as np
import pandas as pd

from sklearn.linear_model import LinearRegression, RidgeCV, Lasso
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRegressor
```

## データの読み込み

publickey さんからデータを拝借し、csv にしておく。

- IT系上場企業の平均給与を業種別にみてみた 2018年版［前編］ ～ ネットベンチャー、ゲーム、メディア系
https://www.publickey1.jp/blog/18/it_2018.html
- IT系上場企業の平均給与を業種別にみてみた 2018年版［後編］ ～ パッケージソフトウェア系、SI／システム開発系、クラウド／キャリア系企業
https://www.publickey1.jp/blog/18/it_2018_si.html

このデータを `data/salary.csv` として保存する。
データを２次公開してよいかどうかは微妙なところなので、各々でこの作業を行ってほしい。

```python
df = pd.read_csv('./data/salary.csv')
```

## 学習モデルを定義

従業員数と平均年齢を説明変数として、年収との間に相関があるのでは？という直感から、そういうモデルを組み立てる。
基本的には DataFrame から説明変数を抜き出すところ以外は変わらないので、そこだけメソッド化。


```python
def prepare_for_model_n_worker_describes_salary(df):
    x = [[v] for v in df['n_workers'].values]
    y = df['mean_salary'].values
    return (x, y)

def prepare_for_model_age_describes_salary(df):
    x = [[v] for v in df['mean_age'].values]
    y = df['mean_salary'].values
    return (x, y)
```

## どのアルゴリズムが良いか比較する

各種リグレッサーを使って比較。
自由度が高いモデルは overfitting に注意。


```python
regressors = [
    LinearRegression(),
    RidgeCV(),
    Lasso(),
    RandomForestRegressor(),
    XGBRegressor(),
]

scores = {}
n = 10

# n回繰り返して平均を取る
for i in range(n):
    #
    # サンプリングの仕方が雑だけど、ざっと比較できれば良い（ちゃんとクロスバリデーション書くの面倒くさい）
    # sklearn にクロスバリデーションが簡単に書けるやつがあるのは知ってるよ
    # でも DataFrame 突っ込めるんだっけ？とか、API 調べるの面倒だよ
    # 何なら読んでくれた人にコメントで書いておいてほしい
    #

    df_train = df.sample(n=int(df.shape[0]/2))
    x_w_train, y_w_train = prepare_for_model_n_worker_describes_salary(df_train)
    x_a_train, y_a_train = prepare_for_model_age_describes_salary(df_train)

    df_test = df.sample(n=int(df.shape[0]/2))
    x_w_test, y_w_test = prepare_for_model_n_worker_describes_salary(df_test)
    x_a_test, y_a_test = prepare_for_model_age_describes_salary(df_test)

    for reg in regressors:
        name = reg.__class__.__name__

        if name not in scores:
            scores[name] = {'n_workers': [], 'ages': []}

        reg.fit(x_w_train, y_w_train)
        score = reg.score(x_w_test, y_w_test)
        scores[name]['n_workers'].append(score)

        reg.fit(x_a_train, y_a_train)
        score = reg.score(x_a_test, y_a_test)
        scores[name]['ages'].append(score)

# 平均スコアの比較
for reg in regressors:
    name = reg.__class__.__name__

    ms_w = np.mean(np.array(scores[name]['n_workers']))
    ms_a = np.mean(np.array(scores[name]['ages']))

    print('scores by {},\n\tn_workers = {}\n\tages = {}\n'.format(name, ms_w, ms_a))

```

```
    scores by LinearRegression,
    	n_workers = -0.10807971772977312
    	ages = 0.43705004393376373

    scores by RidgeCV,
    	n_workers = -0.10807969763739456
    	ages = 0.43700566128245233

    scores by Lasso,
    	n_workers = -0.10807527879694716
    	ages = 0.437042904756201

    scores by RandomForestRegressor,
    	n_workers = 0.34281493519643963
    	ages = 0.49390979300492993

    scores by XGBRegressor,
    	n_workers = 0.37043473644605884
    	ages = 0.5042511965145637
```

## 細かいことはさておき

XGBoostRegressor がどちらの指標でも良いっぽい。
平均年齢の方に関しては、線形モデルでもそこそこ精度が出ているので、年齢との相関は強いっぽいなぁ、雑な解析だけど。

## なので XGBoost を使って予測してみる

結果は csv にして spreadsheet で表示する。
pandas でグラフ表示すればいいじゃん！というのはごもっともなんだけど、スプレッドシートの方が直感的で早い。
後でこねくり回すわけでなければスプレッドシートの方が可視化とかにも簡単（このデータ数ならば）。

※ `train_*` のメソッドが見当たらないけど、おそらく第一引数のモデルを学習しているだけ

```python
reg_w = XGBRegressor()
reg_a = XGBRegressor()

x_w, y_w = prepare_for_model_n_worker_describes_salary(df)
reg_w = train_n_worker_describes_salary(reg_w, x_w, y_w)

x_a, y_a = prepare_for_model_age_describes_salary(df)
reg_a = train_age_describes_salary(reg_a, x_a, y_a)

diffs_w = []
diffs_a = []

pred_w = reg_w.predict(x_w)
pred_a = reg_a.predict(x_a)

count = 0

result = {}

for d in df.itertuples():
    actual = d.mean_salary
    expected_w = pred_w[count]
    expected_a = pred_a[count]
    ratio_w = actual / expected_w
    ratio_a = actual / expected_a
    count += 1

    result[d.name] = {
        'name': d.name,
        'expected_w':  expected_w,
        'expected_a': expected_a,
        'actual': actual,
        'ratio_w': ratio_w,
        'ratio_a': ratio_a,
    }

df_result = pd.DataFrame(result).T
df_result.to_csv('samary_of_salary.csv')

```

## 結果

見にくくなるので、最下部に tsv の生データを貼り付けている。
expected(X) が指標 `X` から期待される年収なのに対し、actual が実際の平均年収、
ratio(X) は指標 `X` の期待年収と実際の年収との比である。
ただし、ratio(product) は ratio(n workers) と ratio(mean age) の積で、
従業員数と平均年齢の両方の影響を加味した比である。

注目すべきは ratio（...）で、ratio(n workers) が大きいほど、
この従業員数にしては平均給与が高い！という意味になる（予測モデルが妥当ならばという条件付き）。
同様に、ratio(mean age) が大きいほど、この平均年齢にしては平均給与が高い！という意味になる（同上）。

つまり、両ratio が高い企業は、他に比べて良く人材に投資している企業だと考えることができる。
ただし、ここには業種、業態、役員数、役職者数などの変数が入っていないため、
実際には給与が高いのは役員手前の役職持ちだけで、平社員は他企業に比べて低い、なんてこともあり得る。
他のどの統計もそうだが、一般にこの指標が高いからこの企業は優良だ、というのは難しく、
多角的に見て、こういった指標で切ったときにこうなっているから、この企業ではここを見なければいけない、
という論理展開が必要である。

※ ratio(product) で降順

```tsv
name	expected(n workers)	expected(mean age)	actual	ratio(n workers)	ratio(mean age)	ratio(product)
(株)オービック	773.7681274	655.1433105	877	1.13341448	1.338638411	1.517232158
テクマトリックス(株)	576.3709717	642.0036621	746	1.294305294	1.161987141	1.503966109
(株)ミクシィ	576.3709717	522.5099487	666	1.155505799	1.274616879	1.472827195
東洋ビジネスエンジニアリング(株)	595.1005859	753.4799194	807	1.356073274	1.071030533	1.452395882
ソースネクスト(株)	623.1326904	623.7352295	749	1.201991183	1.200830039	1.44338712
(株)ジャストシステム	751.9296875	833.3251953	951	1.264745914	1.141211145	1.443342132
(株)ディー・エヌ・エー	642.9976196	637.8458252	757	1.177298293	1.186807172	1.397226058
ＩＳＩＤ	699.3291626	827.1504517	897	1.282657793	1.084446002	1.390973115
(株)ユーザベース	563.3231812	592.6373901	672	1.192920907	1.133914281	1.352670052
(株)三菱総合研究所	793.4802246	886.6829834	975	1.228764082	1.099603825	1.351153685
(株)野村総合研究所	1064.203491	957.4052124	1166	1.095655116	1.217875133	1.33437112
トレンドマイクロ(株)	758.9573364	833.3251953	915	1.205601364	1.098010723	1.323763225
任天堂（株）	878.0438843	702.6268311	903	1.028422401	1.285177224	1.321705047
インフォテリア(株)	609.8165894	675.8973389	737	1.208560103	1.090402281	1.317816693
(株)サイバーエージェント	699.3291626	538.7087402	703	1.005249084	1.30497233	1.311822239
ヤフー(株)	745.1188965	603.0393677	767	1.029365922	1.271890429	1.309240664
(株)ＮＴＴデータイントラマート	610.6682739	642.0036621	716	1.172485997	1.115258436	1.307624899
クックパッド(株)	591.1740723	572.6190796	650	1.099506948	1.135135072	1.248088898
ＬＩＮＥ(株)	699.3291626	590.2640381	715	1.022408385	1.211322313	1.23846609
ＫＤＤＩ(株)	865.4657593	820.6074219	936	1.081498592	1.140618492	1.233577293
(株)Ｇｕｎｏｓｙ	602.3768921	549.0093384	638	1.059137574	1.162093166	1.230816536
(株)カカクコム	624.0244141	604.8148804	681	1.091303456	1.125964361	1.228768799
日本オラクル(株)	900.0001831	955.5774536	1027	1.141110879	1.074742812	1.226400715
(株)ＬＩＦＵＬＬ	624.0244141	642.4219971	701	1.123353485	1.091183059	1.225784292
グリー(株)	758.9573364	672.2853394	779	1.026408156	1.158734178	1.189334211
楽天(株)	728.9985352	590.2640381	707	0.9698236223	1.197769057	1.161624725
(株)ＮＴＴデータ	830.8305664	702.6268311	821	0.9881677844	1.168472315	1.154646699
(株)マネーフォワード	578.4611816	572.6190796	614	1.061436825	1.072266052	1.138142674
(株)朝日ネット	602.3768921	675.8973389	679	1.127201274	1.004590433	1.132375615
(株)セック	591.1740723	642.0036621	653	1.104581596	1.017128154	1.12350104
バリューコマース(株)	578.4611816	587.9794922	617	1.066622998	1.049356327	1.119267591
(株)ブロードバンドタワー	602.3768921	642.0036621	657	1.090679288	1.023358649	1.116156083
伊藤忠テクノソリューションズ(株)	804.5678101	819.8688965	855	1.062682336	1.04284966	1.108217913
(株)ドリコム	587.0799561	554.1394043	600	1.022007299	1.082760034	1.106588657
ソフトバンク・テクノロジー(株)	655.1060791	623.7352295	668	1.019682188	1.070967244	1.092046223
(株)デジタルガレージ	595.1005859	587.9794922	617	1.036799517	1.049356327	1.087972132
(株)コロプラ	604.1364136	492.9030457	568	0.9401850099	1.152356442	1.083428253
新日鉄住金ソリューションズ(株)	804.5678101	833.3251953	837	1.040310076	1.004409809	1.044897645
(株)大塚商会	766.689209	819.8688965	808	1.053882056	0.9855234214	1.03862545
(株)オウケイウェイヴ	563.3231812	587.9794922	586	1.040255433	0.9966333993	1.036753309
(株)ユビキタスＡＩコーポレーション	641.7440796	758.2072144	709	1.104801778	0.9351005722	1.033100775
ウォンテッドリー(株)	506.3501587	507.0843811	514	1.015107809	1.013638004	1.028951853
日本ユニシス(株)	804.5678101	758.2072144	790	0.9818936206	1.041931526	1.023065919
日本ファルコム(株)	506.3501587	590.2640381	550	1.086204854	0.9317863948	1.012110905
(株)ｇｕｍｉ	576.3709717	604.8148804	593	1.028851259	0.9804652948	1.008752953
ビジネスコンサルタント	647.6647339	642.4219971	646	0.9974296364	1.005569552	1.002984873
(株)オービック	647.6647339	642.4219971	646	0.9974296364	1.005569552	1.002984873
アイティメディア(株)	610.6682739	702.6268311	656	1.074232981	0.9336392677	1.002946093
(株)ｅｎｉｓｈ	566.3271484	604.8148804	586	1.03473761	0.9688915055	1.002548481
(株)エニグモ	509.8183899	554.1394043	531	1.041547364	0.9582426297	0.9980550848
エキサイト(株)	578.4611816	603.0393677	584	1.009575091	0.9684276538	0.9777004366
(株)レアジョブ	587.5178833	604.8148804	589	1.002522675	0.9738517009	0.9763084123
(株)クラウドワークス	566.3271484	492.9030457	522	0.9217287242	1.059031801	0.9761400305
(株)はてな	563.3231812	538.7087402	543	0.9639226969	1.007965825	0.9716011368
(株)ユーザーローカル	641.7440796	553.9151611	587	0.9146948428	1.059729073	0.9693287175
(株)駅探	509.8183899	653.8118896	568	1.114122227	0.8687514085	0.9678952541
(株)ベリサーブ	615.4140015	652.8118286	623	1.012326659	0.9543331979	0.9660969378
(株)ＳＲＡホールディングス	657.1419678	682.7514648	658	1.001305703	0.9637474746	0.9650058425
ＫＬａｂ(株)	576.3709717	554.1394043	554	0.9611865053	0.999748431	0.9609447005
サイオス(株)	680.9452515	820.6074219	729	1.070570649	0.8883663254	0.9510589138
(株)テラスカイ	578.4611816	623.7352295	585	1.011303815	0.9378979611	0.9484997864
富士通（株）	829.2805176	794.8381958	790	0.9526330153	0.9939129802	0.9468343193
サイボウズ(株)	587.0799561	637.8458252	595	1.013490571	0.9328273017	0.9454116748
(株)インタースペース	527.368103	523.9463501	511	0.9689626602	0.9752906951	0.9450202664
(株)インターネットイニシアティブ	763.3681641	623.7352295	669	0.876379225	1.072570489	0.9399784937
フリービット(株)	578.4611816	604.4632568	573	0.9905591217	0.9479484378	0.9389989719
ネットワンシステムズ(株)	769.1536255	833.3251953	773	1.005000788	0.9276090587	0.9322478353
(株)ＮＴＴドコモ	856.6231079	957.4052124	874	1.020285341	0.9128841045	0.9314022701
(株)セゾン情報システムズ	655.1060791	733.6549683	668	1.019682188	0.9105097476	0.9284305715
ＧＭＯインターネット(株)	576.3709717	546.3873291	540	0.9368965936	0.9883098879	0.9259441674
(株)ＡＳＪ	506.3501587	604.4632568	532	1.050656331	0.8801196665	0.9247032997
日本プロセス(株)	576.3709717	642.0036621	584	1.013236316	0.909652132	0.9216925751
(株)ソリトンシステムズ	576.3709717	755.1387329	633	1.098251007	0.8382565645	0.9206161161
(株)ネオジャパン	563.3231812	590.2640381	553	0.9816744961	0.936868866	0.9197002719
(株)ファンコミュニケーションズ	518.9317627	523.9463501	499	0.961590783	0.9523875868	0.9158071253
(株)電算システム	576.3709717	652.8118286	587	1.018441297	0.8991871383	0.9157693154
(株)エイチーム	518.9317627	532.6176147	502	0.9673718899	0.9425148288	0.9117623512
(株)アドウェイズ	576.3709717	529.3322144	527	0.9143416756	0.9955940442	0.9103131265
ＴＩＳ(株)	728.9985352	675.8973389	669	0.9176973173	0.9897952863	0.9083324788
(株)みんなのウェディング	563.3231812	590.2640381	549	0.9745737764	0.9300922377	0.9064435045
ネットイヤーグループ(株)	610.6682739	642.0036621	592	0.9694297629	0.9221131201	0.8939239034
(株)リブセンス	591.1740723	529.3322144	527	0.8914464025	0.9955940442	0.8875187291
(株)ラック	642.9976196	675.8973389	621	0.9657889564	0.9187785841	0.8873462099
(株)ぐるなび	631.7301636	587.9794922	574	0.9086157874	0.9762245242	0.8870130147
エン・ジャパン(株)	606.3043213	460.5044556	495	0.8164216922	1.074908167	0.8775783443
ＳＣＳＫ(株)	766.689209	792.5020752	726	0.9469286792	0.9160859293	0.867468039
(株)ネクソン	591.1740723	603.0393677	556	0.9405013279	0.921996191	0.8671386419
(株)マクロミル	603.6443481	534.8388672	528	0.8746872254	0.9872132195	0.8635027918
(株)メルカリ	600.772522	492.9030457	502	0.8355908129	1.01845587	0.851012368
富士ソフト(株)	653.9989014	623.7352295	586	0.89602597	0.9395012055	0.841817479
さくらインターネット(株)	587.0799561	642.0036621	561	0.9555768243	0.8738267912	0.8350086301
(株)ブランジスタ	515.0378418	450.776886	440	0.8543061583	0.9760926385	0.8338819521
(株)キャリアデザインセンター	576.3709717	460.5044556	466	0.8085070604	1.011933749	0.8181555804
(株)オークファン	587.5178833	581.1178589	525	0.8935898207	0.9034311921	0.807296917
(株)オールアバウト	566.3271484	579.4524536	514	0.9076026135	0.8870443067	0.8050837311
(株)イード	555.630127	623.7352295	525	0.9448731711	0.8417032984	0.7953028647
(株)パピレス	509.8183899	523.9463501	460	0.9022820854	0.8779524849	0.7921607989
ＧＭＯペパボ(株)	574.8297729	532.6176147	491	0.8541659168	0.9218621135	0.7874231973
(株)ＳＨＩＦＴ	576.3709717	590.2640381	517	0.8969917387	0.8758792111	0.7856564164
(株)カプコン	676.6923218	604.4632568	563	0.8319881605	0.931404835	0.7749177953
(株)コア	603.6443481	724.6617432	579	0.9591740597	0.798993469	0.7663738093
ディップ(株)	616.184021	460.5044556	465	0.7546446908	1.009762217	0.762011696
ジョルダン(株)	566.3271484	614.4620972	514	0.9076026135	0.8365039965	0.7592132134
(株)メンバーズ	524.5172119	450.776886	423	0.8064558996	0.9383799683	0.7567620616
(株)エヌアイデイ	603.6443481	702.6268311	562	0.9310117816	0.7998555921	0.7446749798
アウンコンサルティング(株)	444.492981	450.776886	385	0.8661554096	0.8540810587	0.7397669292
(株)ボルテージ	518.9317627	460.5044556	416	0.8016468251	0.9033571662	0.7241734042
クルーズ(株)	563.3231812	492.9030457	448	0.7952806044	0.9089008558	0.7228312219
(株)ザッパラス	566.3271484	590.2640381	491	0.8669900452	0.831831127	0.7211893063
(株)フルスピード	515.0378418	538.7087402	434	0.8426565289	0.8056301441	0.6788695007
ソーバル(株)	603.6443481	603.0393677	494	0.8183626692	0.8191836661	0.6703893315
(株)オウチーノ	509.8183899	587.9794922	448	0.8787442919	0.761931336	0.6695428123
ＡｐｐＢａｎｋ(株)	506.3501587	517.3466187	389	0.7682430692	0.7519136803	0.5776524735
(株)Ａｉｍｉｎｇ	498.0993652	410.3424072	340	0.6825947265	0.8285763158	0.5655818237
(株)日本一ソフトウェア	526.8168945	522.5099487	388	0.7364987798	0.7425695931	0.5469015992
ＧＭＯクラウド(株)	566.3210449	493.6746216	379	0.6692317077	0.7677121396	0.5137773062
```