1. 問題描述
2. 問題假設
3. 問題解決及可視化分析
- 初始化遊戲
- 假設一 :不允許負債情況(財富值低於0即退出遊戲)
- 假設二 :負債情況(投機者:即使財富爲負依然消費)
- 假設三 :努力工作(奮鬥者:負債情況下獲得財富的機率多1%)
- 假設四 :存款利率(投資者:持有財富的年利率是3%
- 總結
1.問題描述
房間內有 100 人,每人有 100 塊,每分鐘隨機 給另一個人 1 塊錢,最後這個房間內的財富分佈怎樣?
2.問題假設
我們可以用這個遊戲模擬現實社會上的財富運行及分配,有的人花錢,有的人掙錢,但是總資產不變。
假設:1.每個人在18歲帶着100元的初始資金開始玩遊戲;
2.每天玩一次,一直玩到80歲的人均壽命。
在現實社會中人的平均壽命爲80歲,那麼一生共需要玩大約20000次遊戲,也就是說有20000次機會選擇收錢或消費,只不過是隨即分配的。
在此基礎上,爲進一步模擬現實社會,分爲以下四種情況:
假設一 :不允許負債情況(財富值低於0即退出遊戲)
假設二 :負債情況(投機者:即使財富爲負依然消費)
假設三 :努力工作(奮鬥者:負債情況下獲得財富的機率多1%)
假設四 :存款利率(投資者:持有財富的年利率是3%)
3.問題解決
- 初始化遊戲
#
# 初始化模擬世界
#
from random import choice, sample
import numpy as np
nLoops = 20000 # 分配的次數
nGamers = 100 # 參與分配的人數
deposit = 100 # 每個人初始財富數量
consume = 1 # 每次分配消費或者獲得的財富
gamers = {} # 用字典的方式保存每個人的財富數量並初始化
for gamer in range(nGamers):
gamers[gamer] = deposit
計算每次隨機分佈的個人財富
# 計算每一次隨機分配後的個人財富
def epoch(gamers, nGamers, consume, loan=False):
"""
模擬每次分配的情況
1 遍歷全體參與者,獲得參與者ID和擁有的財富
2 隨機挑選除自己以外的一個參與者
3 自己消費財富同時挑選的參與者獲得相應財富(注:考慮負債)
參數:
gamers - 分配遊戲的參與者和其攜帶的財富數量;數據類型:字典,其中key爲參與者ID,value爲對應的財富數量
nGamers - 參與分配遊戲的總人數;數據類型:大於1的正整數
consume - 參與每次分配消費或者獲得的財富;數據類型:正整數
loan - 當參與者攜帶的財富小於零的時候,是否允許參與本次分配的消費活動
"""
for nid, nvalue in gamers.items():
others = list(range(0,nGamers))
del(others[nid])
to_gamer = choice(others)
if gamers[nid] <= 0 and not loan:
continue
gamers[to_gamer] += consume
gamers[nid] -= consume
return gamers
可視化結果:
def vis_simulation(nGamers, gamers, lucky_gamers=None):
"""
模擬世界的財富分配 - 可視化結果
參數:
nGamers - 參與分配遊戲的總人數;數據類型:大於1的正整數
gamers - 分配遊戲的參與者和其攜帶的財富數量;數據類型:字典,其中key爲參與者ID,value爲對應的財富數量
"""
from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams['font.sans-serif'] = ['SimHei'] #指定默認字體
plt.rcParams['axes.unicode_minus']=False #用來正常顯示負號
if lucky_gamers:
new_gamers = []
for i in lucky_gamers:
new_gamers.append(gamers[i])
sort_gamers = sorted(gamers.values())
new_index = []
for i in new_gamers:
index = sort_gamers.index(i)
new_index.append(index)
# 可視化結果
plt.figure(figsize=(18,6))
plt.subplot(131)
plt.hist(gamers.values())
#plt.xlim([0,400])
#plt.ylim([0,30])
plt.title("財富的總體分佈")
plt.subplot(132)
plt.bar(range(0,nGamers), gamers.values(), width=0.5, color='orange')
if lucky_gamers:
plt.bar(lucky_gamers, new_gamers, width=0.5, color='red')
plt.plot([0,100],[100, 100],color='green',linestyle="-.",linewidth=1)
plt.xlim([0,100])
#plt.ylim([0,400])
plt.title("個人持有財富的分佈")
plt.subplot(133)
plt.bar(range(0,nGamers), sorted(gamers.values()), width=0.5, color='orange')
if lucky_gamers:
plt.bar(new_index, new_gamers, width=0.5, color='red')
plt.plot([0,100],[100, 100],color='green',linestyle="-.",linewidth=1)
plt.xlim([0,100])
#plt.ylim([0,400])
plt.title("排序後的個人持有財富分佈")
plt.show()
- 假設一
不允許負債情況(財富值低於0即退出遊戲):
# 模擬分配 - 不負債的情況
for i in range(nLoops):
gamers = epoch(gamers, nGamers, consume)
print(gamers)
輸出:
可視化結果:
vis_simulation(nGamers, gamers)
- 假設二
負債情況(投機者:即使財富爲負依然消費)
gamers = {} # 用字典的方式保存每個人的財富數量並初始化
for gamer in range(nGamers):
gamers[gamer] = deposit
# 模擬分配 - 允許負債的情況
for i in range(nLoops):
gamers = epoch(gamers, nGamers, consume, loan=True)
vis_simulation(nGamers, gamers)
- 假設三
努力工作(奮鬥者:負債情況下獲得財富的機率多1%)
# 假如有某些比較努力的人們,計算每一次隨機分配後的個人財富
def epoch_better_person(gamers, nGamers, consume, lucky_gamers, loan=False):
"""對於給定人數的遊戲參與者, 每個人都隨機的給其他人指定數量的貨幣(give)
其中loan參數顯示是否允許參與分配的人其財富爲負值(即負債)
"""
pass
gamers = {} # 用字典的方式保存每個人的財富數量並初始化
for gamer in range(nGamers):
gamers[gamer] = deposit
# 模擬分配 - 允許負債的情況 & 存在10個積極努力的參與者(奮鬥者)
lucky_gamers = sample(range(0, nGamers), 10)
for i in range(nLoops):
gamers = epoch_better_person(gamers, nGamers, consume, lucky_gamers, loan=True)
vis_simulation(nGamers, gamers, lucky_gamers=lucky_gamers)
說明一下下:以上代碼來自老師,我做了一下總結與修改,並增添了一個自己的…(嘿嘿)
- 假設四
import matplotlib.pyplot as plt#繪圖庫
import numpy as np#數據分析
import pandas as pd#數據分析
import random #隨機函數
import time#計算時間
import copy#dataframe使用
plt.rcParams['font.sans-serif']=['SimHei'] # 用黑體顯示中文
plt.rcParams['axes.unicode_minus']=False # 正常顯示負號
###定義方法:玩遊戲#####
# 假設3(play_game3):存款利率(投資者:持有財富的年利率是3%)
def play_game3(round_number): #round_number表示遊戲的輪數
id_list = range(100) #定義每個人的編號
id_money_dict = {k: 100 for k in id_list} #定義初始每個人各#100元
round_id_money_dict={} #用於放每一輪遊戲後每一個人的財富值,每一輪的數據都會保存
for round_id in range(1,round_number+1): #進行多輪遊戲
if round_id/365==0:
for i in [0,11,22,33,44,55,66,77,88,99]:
id_money_dict["i"]*=1.03 #每一年計算一次利率
for id in id_money_dict.keys(): #每一輪中的每一個人都進行拿#錢和收錢的遊戲
id_money_dict[id] += -1 #其中一個人拿出一元錢
id_get = random.randint(0, 99) #隨機選出另外一個
#收錢的人
while id_get == id:
id_get = random.randint(0, 99) #如果出錢者
#錢者是同一個人,則重新選一個收錢者
id_money_dict[id_get] += 1 #另外一個人收下一元錢
round_id_money_dict[round_id]=copy.copy(id_money_dict) #每一輪遊戲過後,將數據存儲在字典round_id_money_dict中
data_result=pd.DataFrame(round_id_money_dict) #將每一輪遊戲結束後的數據轉化爲DataFrame格式,便於取用和比較
return(data_result)
###定義方法:繪製柱狀圖#####
def draw1(data,n): #data表示n輪後的數據,n表示遊戲輪數
data=pd.DataFrame(data)
data=data.T
datai = pd.DataFrame({'money':data.iloc[0],'color':'gray'})
datai['color'].loc[0,11,22,33,44,55,66,77,88,99] = 'red'
datai = datai.sort_values(by = 'money').reset_index()
plt.figure(figsize=(14,12))
plt.bar(datai.index,datai['money'],color = datai['color'])
plt.xticks(np.arange(100), datai["index"],fontsize=8,rotation=90)#設置座標值
plt.ylim([-300,500])
plt.xlim([-10,110])
plt.xlabel('玩家編號') #定義橫座標的名稱
plt.ylabel('財富值/元') #定義縱座標的名稱
plt.title(str(n)+'輪遊戲後的財富分佈')
plt.show()
'''
規定年利率爲3%,那麼一年後的財富爲(1.03)*本金
規定id號爲0,11,22,33,44,55,66,77,88,99的人爲投資者
'''
#開始遊戲
data_result=play_game3(20000)
##繪製十年,二十年,三十年,四十年,五十年後財富分佈結果
for i in [3600,7200,10800,14400,18000]:
start=time.time()
draw1(data_result[i],i)
##數據分析
print("%d次遊戲後數據分析:"%i)
#分析id號爲0,11,22,33,44,55,66,76,88,99的人的財富情況
print("投資者的財富值情況:")
for j in [0,11,22,33,44,55,66,76,88,99]:
print(data_result[i][j],end=" ")
##投資者所擁有的財富佔總財富的比例
invest_money=0
for x in [0,11,22,33,44,55,66,76,88,99]:
invest_money+=data_result[i][x]
print("投資者所擁有的財富佔總財富的比例%s%%"%(invest_money/100))
## 分析第n次遊戲,財富值排名前30的Id號
rank_money = np.argsort(data_result[i])[90:100] # 返回排序後各數據的原始下標即從小到大排列財富值後,返回id號
count=0#統計排名前三中那十個人的比例
for m in rank_money:
for n in [0,11,22,33,44,55,66,76,88,99]:
if m==n:
count+=1
print("財富排行榜排名前十的人中,投資者共有%d個,所佔比例爲%s%%"%(count,count/3*10))
end=time.time()#結束時間
print("所用時間爲:"+str(end-start)+"s")
-
總結
1.結合圖表及數據可知,投資者的財富處於不確定的狀態,在18-48歲時投資者的財富一直處於上升階段,並且所有人的財富所佔總體財富的比例也在上升,而48歲即10800次遊戲後投資者所擁有的財富佔總財富的比例開始下降,並且一旦負債之後就難以迴歸原來的初始值,而財富排行榜中,投資者所佔比例也不是很多,告訴我們"投資有風險,需謹慎"2.儘管最成功的玩家不一定是最努力的那個,
但是努力的人大都(80%)混的還不錯。感謝這個殘酷世界還給我們留下一條生路。
那麼,該如何面對這個殘酷的世界?
那就是