一个财富分配游戏:
房间里有100个人,每人都有100元钱,他们在玩一个游戏。每轮游戏中,每个人都要拿出一元钱随机给另一个人,最后这100个人的财富分布是怎样的?
涉及的知识:
np.random.choice
Generates a random sample from a given 1-D array
numpy.random.choice(a, size=None, replace=True, p=None)
- a: 1-D ndarray,如果是int则生成np.arange(a),理解为从a中取样
- size:抽样尺寸, (m, n, k), then m * n * k samples are drawn,默认None返回一个值
- replace:个人理解为True放回采样,False不放回采样
- p:1-D array-like,对应a中每个元素的抽样概率
DataFrame iloc loc
- iloc:整数标签(从0行开始标签)
- loc:轴标签(类似于行名称)
帕累托图绘图步骤(游戏二可视化中有代码)
- sort_values对元素降序排列
- 利用sum计算单个元素在总数中的占比
- 利用cumsum计算概率的累积求和,找到80%的节点
- 用bar画柱状图后,绘制累积的概率图。
- 利用节点进行进行辅助线的标注
游戏一:没有借贷的社会
模型假设:
- 每个人初始基金100元
- 从18岁到65岁,每天玩一次,简化运算按照一共玩17000轮
- 每天拿出一元钱,并且随机分配给另一个人
- 当某人的财富值降到0元时,他在该轮无需拿出1元钱给别人,但仍然有机会得到别人给出的钱
导入需要的包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import time
import warnings
warnings.filterwarnings('ignore')
搭建模型
分为两种情况:
当所有人财富值都>0的时候,每个玩家都需要付1元钱。
当存在财富值=0的玩家,财富值不为0的玩家需要付1元钱。
因此在函数中用if进行筛选,分为两种情况构建函数。
def game1(data,roundi):
if len(data[data[roundi-1]==0])>0:
#当数据包含财富值为0的玩家,为0的玩家不需要出钱
round_i=pd.DataFrame({'pre_round':data[roundi-1],'lost':0})
con=round_i['pre_round']>0#筛选>0的玩家bool值
round_i['lost'][con]=1#符合条件的lost=1
roundi_players_i=round_i[con]#筛选总玩家数用于choice函数
#利用choice函数,随机选择收到1元钱的玩家
choice_i=pd.Series(np.random.choice(person_n,len(roundi_players_i)))
#利用value_counts计算每个玩家收到的钱总数
gain_i=pd.DataFrame({'gain':choice_i.value_counts()})
#按照index连接两个表,并填充缺失值(nan无法参与return中的计算)
round_i=round_i.join(gain_i)
round_i.fillna(0,inplace=True)
#玩家本轮结束的财富=上一轮-付钱(只有财富值>0的lost=1)+得到(通过value_counts计算)
return round_i['pre_round']-round_i['lost']+round_i['gain']
else:
#所有玩家都出1元钱
round_i=pd.DataFrame({'pre_round':data[roundi-1],'lost':1})
choice_i=pd.Series(np.random.choice(person_n,100))
gain_i=pd.DataFrame({'gain':choice_i.value_counts()})
round_i=round_i.join(gain_i)
round_i.fillna(0,inplace=True)
return round_i['pre_round']-round_i['lost']+round_i['gain']
运行模型
#构建最初财富值,均为100
person_n=[x for x in range(1,101)]
fortune=pd.DataFrame([100 for i in range(100)],index&