社會資金流是持續(xù)而有目的性的,你是否曾想過难捌,為何富人會出現(xiàn)膝宁,窮人又為何會出現(xiàn)?窮人和富人究竟如何形成,是否努力就一定能獲得成功根吁,贏得更多金錢员淫?今天,讓我們用python代碼婴栽,來模擬一個小社會满粗,看看財富的分配到底是怎樣的。
游戲規(guī)則:
房間里有100個人愚争,每人都有100元錢映皆,他們在玩一個游戲。每輪游戲中轰枝,每個人都要拿出一元錢隨機給另一個人捅彻,最后這100個人的財富分布是怎樣的?
游戲一:沒有借貸的社會
1.1 模型假設(shè)
- 每個人初始基金100元
- 從18歲到65歲鞍陨,每天玩一次步淹,簡化運算按照一共玩17000輪
- 每天拿出一元錢,并且隨機分配給另一個人
- 當某人的財富值降到0元時诚撵,他在該輪無需拿出1元錢給別人缭裆,但仍然有機會得到別人給出的錢
游戲一,我們假設(shè)分配到財富值為0時可不用出錢寿烟,可看做社會前期澈驼,沒有借貸的日子。
1.2 搭建模型
1.2.1 導入所需函數(shù)庫
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import time
import warnings
warnings.filterwarnings('ignore')
# 不發(fā)出警告
1.2.2 第一輪游戲
第一輪游戲筛武,先不考慮某人財富值會出現(xiàn)0元或以下的情況缝其,這里是100輪內(nèi)。
person_n = [x for x in range(1,101)]
fortune = pd.DataFrame([100 for i in range(100)], index = person_n)
fortune.index.name = 'id'
# 設(shè)定初始參數(shù):游戲玩家100人徘六,起始資金100元
round_r1 = pd.DataFrame({'pre_round':fortune[0],'lost':1})
# 設(shè)定第一輪分配財富之前的情況
choice_r1 = pd.Series(np.random.choice(person_n,100))
gain_r1 = pd.DataFrame({'gain':choice_r1.value_counts()})
# 這一輪中每個人隨機指定給“誰”1元錢内边,并匯總這一輪每個人的盈利情況
round_r1 = round_r1.join(gain_r1)
round_r1.fillna(0,inplace = True)
fortune[1] = round_r1['pre_round'] - round_r1['lost'] + round_r1['gain']
# 合并數(shù)據(jù),得到這一輪每個人“盈虧”多少錢 → 得到這一輪財富分配的結(jié)果
1.2.3 第二輪游戲
第二輪游戲漠其,需要考慮當某人財富值降到0元時辉懒,他在本輪無需拿出1元眶俩,同時可以有機會拿到1元。
person_n = [x for x in range(1,101)]
fortune = pd.DataFrame([100 for i in range(100)], index = person_n)
fortune.index.name = 'id'
# 設(shè)定初始參數(shù):游戲玩家100人纲岭,起始資金100元
round_r1 = pd.DataFrame({'pre_round':fortune[0],'lost':0})
round_r1['lost'][round_r1['pre_round'] > 0] = 1
# 設(shè)定第一輪分配財富之前的情況 → 該輪財富值為0的不需要拿錢給別人
round_players = round_r1[round_r1['pre_round'] > 0]
# 篩選出參與游戲的玩家:財富值>0
choice_r1 = pd.Series(np.random.choice(person_n,len(round_players)))
gain_r1 = pd.DataFrame({'gain':choice_r1.value_counts()})
# 這一輪中每個人隨機指定給“誰”1元錢止潮,并匯總這一輪每個人的盈利情況
round_r1 = round_r1.join(gain_r1)
round_r1.fillna(0,inplace = True)
fortune[1] = round_r1['pre_round'] - round_r1['lost'] + round_r1['gain']
# 合并數(shù)據(jù)喇闸,得到這一輪財富分配的結(jié)果
1.2.4 構(gòu)建模型
把前兩輪游戲匯總成一個函數(shù)模型
def game1(data, roundi):
if len(data[data[roundi - 1] ==0]) > 0:
# 當數(shù)據(jù)包含財富值為0的玩家時
round_i = pd.DataFrame({'pre_round':data[roundi-1],'lost':0})
con = round_i['pre_round'] > 0
round_i['lost'][con] = 1 # 設(shè)定每輪分配財富之前的情況 → 該輪財富值為0的不需要拿錢給別人
round_players_i = round_i[con] # 篩選出參與游戲的玩家:財富值>0
choice_i = pd.Series(np.random.choice(person_n,len(round_players_i)))
gain_i = pd.DataFrame({'gain':choice_i.value_counts()}) # 這一輪中每個人隨機指定給“誰”1元錢燃乍,并匯總這一輪每個人的盈利情況
round_i = round_i.join(gain_i)
round_i.fillna(0,inplace = True)
return round_i['pre_round'] - round_i['lost'] + round_i['gain']
# 合并數(shù)據(jù)刻蟹,得到這一輪財富分配的結(jié)果
else:
# 當數(shù)據(jù)不包含財富值為0的玩家時
round_i = pd.DataFrame({'pre_round':data[roundi-1],'lost':1}) # 設(shè)定每輪分配財富之前的情況
choice_i = pd.Series(np.random.choice(person_n,100))
gain_i = pd.DataFrame({'gain':choice_i.value_counts()}) # 這一輪中每個人隨機指定給“誰”1元錢嘿辟,并匯總這一輪每個人的盈利情況
round_i = round_i.join(gain_i)
round_i.fillna(0,inplace = True)
return round_i['pre_round'] - round_i['lost'] + round_i['gain']
# 合并數(shù)據(jù)红伦,得到這一輪財富分配的結(jié)果
1.2.5 運行模型
執(zhí)行代碼,獲得最終結(jié)果
person_n = [x for x in range(1,101)]
fortune = pd.DataFrame([100 for i in range(100)], index = person_n)
fortune.index.name = 'id'
# 設(shè)定初始參數(shù):游戲玩家100人召调,起始資金100元
starttime = time.time() # 模型開始時間
for round in range(1,17001):
fortune[round] = game1(fortune,round) # 進行17000輪隨機分配模擬
game1_result = fortune.T # 轉(zhuǎn)置后得到結(jié)果數(shù)據(jù) → 列為每一個人的id某残,行為每一輪的財富分配結(jié)果
endtime = time.time() # 模型結(jié)束時間
print('模型總共用時%i秒' % (endtime - starttime))
# 計算時間
1.3 數(shù)據(jù)可視化
把模擬結(jié)果按財富值升序的順序作出柱狀圖,同時輸出圖片壮虫,方便查看囚似。
由于數(shù)據(jù)每輪變化波動較小,這里
- 前100輪徐伐,每10輪繪制一個圖
- 100-1000輪办素,每100輪繪制一個圖
- 1000-17000輪祸穷,每400輪繪制一個圖
os.chdir('C:\\Users\\Hjx\\Desktop\\財富分配游戲一')
def graph1(data,start,end,length):
for n in list(range(start,end,length)):
datai = data.iloc[n].sort_values().reset_index()[n]
plt.figure(figsize = (10,6))
plt.bar(datai.index,datai.values,color='gray',alpha = 0.8,width = 0.9)
plt.ylim((0,400))
plt.xlim((-10,110))
plt.title('Round %d' % n)
plt.xlabel('PlayerID')
plt.ylabel('Fortune')
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.savefig('graph1_round_%d.png' % n, dpi=300)
# 創(chuàng)建繪圖函數(shù)2
graph1(game1_result,0,100,10)
graph1(game1_result,100,1000,100)
graph1(game1_result,1000,17400,400)
print('finished!')
從圖可知需曾,100人的財富值隨游戲回合增加祈远,貧富差距越來越明顯。整體指數(shù)呈拋物線狀桑嘶,不過差距并不明顯逃顶。
模擬實驗開始前以政,我也曾以為無論進行多少輪伴找,100人的財富值并無明顯差異技矮,畢竟每個人每一輪都必須拿出一元衰倦,而得到一元的概率是一樣的。然而現(xiàn)實告訴你我磁,富人和窮人就是這樣出現(xiàn)的夺艰。
1.4 結(jié)果分析
對結(jié)果進行排序,增加累積和
round_17000_1 = pd.DataFrame({'money':game1_result.iloc[17000]}).sort_values(by = 'money',ascending = False).reset_index()
round_17000_1['fortune_pre'] = round_17000_1['money'] / round_17000_1['money'].sum()
round_17000_1['fortune_cumsum'] = round_17000_1['fortune_pre'].cumsum()
round_17000_1
得出結(jié)論:
- 經(jīng)過17000輪,最富有的人財富值為404元相比于初始財富烹植,為4.04倍
- 6%的人掌握著群體約20%的財富草雕,20%的人掌握著群體約50%的財富
- 60%的人財富減少固以,低于100元
- 9%的人財富不到原始財富的10%(即10元以下)
游戲二:允許借貸的社會
2.1 模型假設(shè)
- 每個人初始基金100元
- 從18歲到65歲憨琳,每天玩一次篙螟,簡化運算按照一共玩17000輪
- 每天拿出一元錢遍略,并且隨機分配給另一個人
- 當某人的財富值降到0元時绪杏,允許財富值為負蕾久,即同樣需要拿出1元錢給別人僧著,有機會得到別人給出的錢
游戲二盹愚,我們允許借貸,當財富值為0時同樣需要拿出錢霞篡,可以為負值朗兵,繼續(xù)參與游戲。相當于現(xiàn)實世界的向親友盐欺、銀行冗美、伙伴借錢粉洼,比較符合現(xiàn)今社會叶摄。
2.2 搭建模型
2.2.1 構(gòu)建模型
不同于游戲一蛤吓,這里可直接考慮為一種情況会傲,不限制拿出收獲金錢
def game2(data, roundi):
round_i = pd.DataFrame({'pre_round':data[roundi-1],'lost':1}) # 設(shè)定每輪分配財富之前的情況
choice_i = pd.Series(np.random.choice(person_n,100))
gain_i = pd.DataFrame({'gain':choice_i.value_counts()}) # 這一輪中每個人隨機指定給“誰”1元錢哲戚,并匯總這一輪每個人的盈利情況
round_i = round_i.join(gain_i)
round_i.fillna(0,inplace = True)
return round_i['pre_round'] - round_i['lost'] + round_i['gain']
# 合并數(shù)據(jù)顺少,得到這一輪財富分配的結(jié)果
print('finished!')
2.2.2 運行模型
person_n = [x for x in range(1,101)]
fortune = pd.DataFrame([100 for i in range(100)], index = person_n)
fortune.index.name = 'id'
# 設(shè)定初始參數(shù):游戲玩家100人脆炎,起始資金100元
starttime = time.time() # 模型開始時間
for round in range(1,17001):
fortune[round] = game2(fortune,round) # 進行17000輪隨機分配模擬
game2_result = fortune.T # 轉(zhuǎn)置后得到結(jié)果數(shù)據(jù) → 列為每一個人的id秒裕,行為每一輪的財富分配結(jié)果
endtime = time.time() # 模型結(jié)束時間
print('模型總共用時%i秒' % (endtime - starttime))
# 計算時間
2.3 數(shù)據(jù)可視化
round_17000_2 = pd.DataFrame({'money':game2_result.iloc[17000]}).sort_values(by = 'money',ascending = False).reset_index()
round_17000_2['fortune_pre'] = round_17000_2['money'] / round_17000_2['money'].sum()
round_17000_2['fortune_cumsum'] = round_17000_2['fortune_pre'].cumsum()
round_17000_2.head(50)
2.3.1 財富分布差異隨時間的變化趨勢
利用以上數(shù)據(jù),來看看每個回合財富分布差異的大小
game2_st = game2_result.std(axis = 1)
game2_st.plot(figsize = (12,5),color = 'red',alpha = 0.6,grid = True)
plt.show()
從圖中可以發(fā)現(xiàn)颖低,約6000回合前忱屑,財富標準差變化極快。而6000回合后暇昂,變化趨于穩(wěn)定从铲,在一定斜率上波動食店。
就于我們的游戲規(guī)則,可以得出財富值在每個人35歲左右已形成明顯差異自娩。35歲可以大致判定一個人是否事業(yè)有成。
2.3.2 “35歲”暫時失利姊扔,能否實現(xiàn)逆襲
游戲群體從18歲開始恰梢,為方便計算35歲的失利人群能否逆襲,18-35歲大致為6200個回合摧茴。
這里我們定義暫時失利的人群為6200回合后娃豹,財富值為負的人,看看此后他們能否逆襲(由負變正)
game2_round6200 = pd.DataFrame({'money':game2_result.iloc[6200].sort_values().reset_index()[6200],
'id':game2_result.iloc[6200].sort_values().reset_index()['id'],
'color':'gray'})
game2_round6200['color'][game2_round6200['money'] < 0] = 'red'
id_pc = game2_round6200['id'][game2_round6200['money'] < 0].tolist()
print('財富值為負的玩家id為:\n',id_pc)
# 篩選數(shù)據(jù)
# 設(shè)置顏色參數(shù)
plt.figure(figsize = (10,6))
plt.bar(game2_round6200.index,game2_round6200['money'],color = game2_round6200['color'],alpha = 0.8,width = 0.9)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.ylim((-200,400))
plt.xlim((-10,110))
plt.title('Round 6200')
plt.xlabel('PlayerID')
plt.ylabel('Fortune')
plt.show()
接下來禾锤,我們查看他們6200-17000回合后的財富值變化情況
os.chdir('C:\\Users\\QJ\\Desktop\\項目13\\game2')
def graph2(data,start,end,length):
for n in list(range(start,end,length)):
datai = pd.DataFrame({'money':data.iloc[n],'color':'gray'})
datai['color'].loc[id_pc] = 'red'
datai = datai.sort_values(by = 'money').reset_index()
plt.figure(figsize = (10,6))
plt.bar(datai.index,datai['money'],color=datai['color'],alpha = 0.8,width = 0.9)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.ylim((-200,400))
plt.xlim((-10,110))
plt.title('Round %d' % n)
plt.xlabel('PlayerID')
plt.ylabel('Fortune')
plt.savefig('graph2_round_%d.png' % n, dpi=200)
graph2(game2_result,6200,17000,500)
print('finished!')
最終,10人只有3人能逆襲成功逼争。當中我們可以發(fā)現(xiàn)在在42歲,有4人逆襲且財富值能位列40名前后杂伟。然而在社會資金流運轉(zhuǎn)下,最終只有3人逆襲越平,且財富值均屬于超低水平。
2.4 結(jié)果分析
返回到游戲二整體數(shù)據(jù)书闸,得出結(jié)論:
- 經(jīng)過17000輪嫌术,最富有的人財富值為498元相比于初始財富,為4.98倍
- 5%的人掌握著群體約20%的財富,15%的人掌握著群體約50%的財富
- 53%的人財富減少院领,低于100元
- 25%的人破產(chǎn),財富值為負數(shù)
對比游戲一和游戲二强法,我們可以發(fā)現(xiàn),在允許借貸的條件下
- 最富有的人財富值容易更高
- 社會總資金更集中于少數(shù)人手里
- 貧富差距增大,破產(chǎn)人群數(shù)量大
回歸現(xiàn)實
破產(chǎn)人群并沒有模擬實驗的數(shù)字那么嚇人置媳,這是由于收入支出的不對等和社會福利的影響靶橱。
發(fā)現(xiàn)沒有关霸,模擬實驗把每個人的收入支出幾率對等化膘掰,然而現(xiàn)實并不會出現(xiàn)每個個體一樣的工作待遇和消費支出凡伊,所以現(xiàn)實模型來得更為復雜多變。
為了繼續(xù)游戲,對應(yīng)現(xiàn)實蛹疯,我們假設(shè)有10個人勤奮努力狼纬,獲得1%的競爭優(yōu)勢,看看財富分配又會出現(xiàn)怎樣的變化。
游戲三:努力就一定有回報柠贤?
3.1 模型假設(shè)
- 每個人初始基金100元
- 從18歲到65歲餐弱,每天玩一次瓢谢,簡化運算按照一共玩17000輪
- 每天拿出一元錢论笔,并且隨機分配給另一個人
- 當某人的財富值降到0元時尉剩,允許財富值為負,即同樣需要拿出1元錢給別人朗鸠,有機會得到別人給出的錢
- 其中沟启,有10人勤奮努力芽卿,獲得1%的競爭優(yōu)勢(即每輪有0.0101的概率拿到1元肌毅,其他人則為0.899/90)
3.2 搭建模型
3.2.1 構(gòu)建模型
這里,設(shè)置努力的10個人id 分別為:[1,11,21,31,41,51,61,71,81,91],方便后續(xù)跟蹤觀察。
person_p = [0.899/90 for i in range(100)]
for i in [1,11,21,31,41,51,61,71,81,91]:
person_p[i-1] = 0.0101
# 設(shè)置概率
def game3(data, roundi):
round_i = pd.DataFrame({'pre_round':data[roundi-1],'lost':1}) # 設(shè)定每輪分配財富之前的情況
choice_i = pd.Series(np.random.choice(person_n,100, p = person_p))
gain_i = pd.DataFrame({'gain':choice_i.value_counts()}) # 這一輪中每個人隨機指定給“誰”1元錢,并匯總這一輪每個人的盈利情況
round_i = round_i.join(gain_i)
round_i.fillna(0,inplace = True)
return round_i['pre_round'] - round_i['lost'] + round_i['gain']
# 合并數(shù)據(jù),得到這一輪財富分配的結(jié)果
print('finished!')
運行模型
person_n = [x for x in range(1,101)]
fortune = pd.DataFrame([100 for i in range(100)], index = person_n)
fortune.index.name = 'id'
# 設(shè)定初始參數(shù):游戲玩家100人,起始資金100元
starttime = time.time() # 模型開始時間
for round in range(1,17001):
fortune[round] = game3(fortune,round) # 進行17000輪隨機分配模擬
game3_result = fortune.T # 轉(zhuǎn)置后得到結(jié)果數(shù)據(jù) → 列為每一個人的id贴彼,行為每一輪的財富分配結(jié)果
endtime = time.time() # 模型結(jié)束時間
print('模型總共用時%i秒' % (endtime - starttime))
# 計算時間
3.3 數(shù)據(jù)可視化
os.chdir('C:\\Users\\QJ\\Desktop\\項目13\\game3')
plt.figure(figsize = (10,6))
data0 = pd.DataFrame({'money':game3_result.iloc[0],'color':'gray'})
data0['color'].loc[[1,11,21,31,41,51,61,71,81,91]] = 'red'
plt.bar(data0.index,data0['money'],color=data0['color'],alpha = 0.8,width = 0.9)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.ylim((-200,400))
plt.xlim((-10,110))
plt.title('Round %d' % 0)
plt.xlabel('PlayerID')
plt.ylabel('Fortune')
plt.savefig('graph3_round_%d.png' % 0, dpi=200)
# 繪制起始圖片
def graph3(data,start,end,length):
for n in list(range(start,end,length)):
datai = pd.DataFrame({'money':data.iloc[n],'color':'gray'})
datai['color'].loc[[1,11,21,31,41,51,61,71,81,91]] = 'red'
datai = datai.sort_values(by = 'money').reset_index()
plt.figure(figsize = (10,6))
plt.bar(datai.index,datai['money'],color=datai['color'],alpha = 0.8,width = 0.9)
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.ylim((-200,400))
plt.xlim((-10,110))
plt.title('Round %d' % n)
plt.xlabel('PlayerID')
plt.ylabel('Fortune')
plt.savefig('graph3_round_%d.png' % n, dpi=200)
# 創(chuàng)建繪圖函數(shù)2
graph3(game3_result,10,100,10)
graph3(game3_result,100,1000,100)
graph3(game3_result,1000,17400,400)
print('finished!')
一分耕耘一分收獲专普,努力的10人都沖到群體前列策橘,財富值均有所提升买决,更包攬財富榜前三。所以說,努力是有回報的羹奉。
3.4 結(jié)果分析
富人和窮人的區(qū)別
模擬游戲考慮的角度較為簡單耕挨,但清晰可見的是富人和窮人的關(guān)鍵區(qū)別無非兩個字——努力俗孝。窮人總在抱怨壯志難酬酒甸,卻很少發(fā)現(xiàn)富人之所以為富,在于他肯多下的1%努力赋铝,這將在多年后形成明顯的差異插勤。
然而現(xiàn)實更殘酷,富人往往付出窮人500%的努力革骨,甚至更多农尖。馬云上千億身家,花費多少倍常人的努力良哲,無法估量盛卡。