SE_BOKUのまとめノート的ブログ

SE_BOKUが知ってること・勉強したこと・考えたことetc

平等さを突き詰めると不平等になることを確かめる/Pythonサンプル

f:id:arakan_no_boku:20190717231548j:plain

目次

平等さを突き詰めると不平等になることを実験する

池谷裕二さんの本に書いてあった「平等さを突き詰めると不平等になるのは、至って当たり前の統計学的事実である」という説をプログラムで確かめてみます。 

脳はなにげに不公平 パテカトルの万脳薬

脳はなにげに不公平 パテカトルの万脳薬

 

 

実験のルール

実験のルールはこうです。

  1. 1000人に1万円ずつ配る。
  2. 乱数表で2人をランダムに選び出す。
  3. 1人目に選ばれた人は、2人目の人に200円を渡す。
  4. 2と3を100万回繰り返す

最初に全員が1万円もっているのだから完全に「平等」な状態です。

そこからランダムに200円の受け渡しをするのですから、えこひいきも何もなく、これも「平等」な条件でのやりとりになります。

このルールのどこにも不平等はありません。

これを100万回繰り返したあとで、

  • 大きな「貧富の差」が生まれているのか。
  • 所持金の差がない状態をキープしているのか

どちらなんだろう?・・という実験です。 

 

Pythonプログラムソース

人を100人も集めるのは無理なので、プログラムでやります。

ソースはこんな感じです。

py_sim01.py

import matplotlib.pyplot as plt
import random

# 最初に全員が保持する金額
INITIAL_INCOME = 10000
# 一回のトレードで受け渡しをする金額
TRANSACTION_AMOUNT = 200
# トレードを繰り返す回数
REPEAT_COUNT = 1000000
# 処理対象とする人数
NUMBER_OF_PEOPLE = 1000

# 10000円ずつもった1000人を生成
current_income_list = [INITIAL_INCOME for dummy in range(NUMBER_OF_PEOPLE)]
# 乱数であたった一人目から二人目に金額をうつす
for i in range(REPEAT_COUNT):
    provider = random.randrange(0, NUMBER_OF_PEOPLE)
    recipient = random.randrange(0, NUMBER_OF_PEOPLE)
    current_income_list[provider] -= TRANSACTION_AMOUNT
    current_income_list[recipient] += TRANSACTION_AMOUNT

# 1000円レンジでカウントに使う辞書
income_distribution_dic = {
    'MIN': 0,
    '-11': 0,
    '-10': 0,
    '-9': 0,
    '-8': 0,
    '-7': 0,
    '-6': 0,
    '-5': 0,
    '-4': 0,
    '-3': 0,
    '-2': 0,
    '-1': 0,
    'CTR': 0,
    '1': 0,
    '2': 0,
    '3': 0,
    '4': 0,
    '5': 0,
    '6': 0,
    '7': 0,
    '8': 0,
    '9': 0,
    '10': 0,
    '11': 0,
    '12': 0,
    '13': 0,
    '14': 0,
    '15': 0,
    'MAX': 0
}

# カウント時に比較する金額レンジをもつ辞書
income_forwork_dic = {
    'MIN': -2000,
    '-11': -1000,
    '-10': 0,
    '-9': 1000,
    '-8': 2000,
    '-7': 3000,
    '-6': 4000,
    '-5': 5000,
    '-4': 6000,
    '-3': 7000,
    '-2': 8000,
    '-1': 9000,
    'CTR': 10000,
    '1': 11000,
    '2': 12000,
    '3': 13000,
    '4': 14000,
    '5': 15000,
    '6': 16000,
    '7': 17000,
    '8': 18000,
    '9': 19000,
    '10': 20000,
    '11': 21000,
    '12': 22000,
    '13': 23000,
    '14': 24000,
    '15': 25000,
    'MAX': 99999
}
# 辞書にカウントしていく
for r in current_income_list:
    for key_a, val_a in income_forwork_dic.items():
        if r <= val_a:
            income_distribution_dic[key_a] += 1
            break
# 棒グラフの表示
plt.bar(x=income_distribution_dic.keys(),
        height=income_distribution_dic.values())
plt.show()

個別の金額を表示するのではなく、 -2000円未満から25000円超まで1000円きざみの枠を作り、そこに金額比較でカウントしています。 

 

結果のグラフを現実と比較

上記のプログラムの結果、表示したグラフはこんな感じです。

f:id:arakan_no_boku:20190720000351p:plain

左(MIN)に行くほど貧乏(MINだと-3000円以下)、右(MAX)に行くほど金持ち(MAXだと25000円以上)です。

結果的に貧富の差はでました。

この結果を、日本の実際の所得分布状況グラフと形を比べてみます。 

2018年度の資料(こちらのPDF)の所得の分布状況のグラフはこうです。

f:id:arakan_no_boku:20190720001020p:plain

形は、ちょっと違います。

でも、実験の方は、スタートラインで全員が1万円もっている前提でやってます。

現実世界でこれはありえません。

 

実験の設定を現実よりに変えてみる

グラフの単位が、現実所得のほうは100万円単位で、実験は1000円単位です。

この単位をあわせると、実験は全員が1000万円持っているところから始めていることになるので、ちょっと違和感があります。

なので、今度は INITIAL_INCOME = 0.、最初はみんなが0円スタートにしました。

ただ、これだとMINの人数が異常に増えるので、MINだけグラフに表示しないようにしてみました。

py_sim02.py

f:id:arakan_no_boku:20190720003215p:plain

すると、実際の所得分布と形が似てきました。

もっとも、MIN(-3000以下)をグラフから切り捨てるのはノーマルではありません。

でも、現実世界でも、極端な低所得者については「生活保護」という形でMINに相当する人達にバイアスがかかっていますし、そのセーフティネットにも拾われない人達はグラフに反映していない可能性もあります。

だから。

実験でランダムにお金のやりとりをしただけで、現実の所得分布に似た形のグラフが現れるというのは面白いな・・と思いました。

金持ちになるか貧乏になるか。

そのどちらになるかは乱数の発生に近い偶然(運?)に支配される部分が大きい。

かつ、貧富の差が生まれるのは自然の摂理みたいなものである。

そういうことなのかもしれません。

個人的には認めたくない気もしますけど・・まあ、面白かったからよしとします。

今回はこんなところで。

ではでは。