如何使用Python生成正态分布的人员身高体重信息?
下面是生成的数据的分布情况,身高数据在各个区间大致呈正态分布。
对应的代码如下,先用pd.cut进行各个区间分桶,然后使用sort_index按照区间名排序。
df = pd.read_csv('./datasets/boygirl200.csv', encoding='gbk')
des = df.describe()
bins = range(des.height['min'].astype(int), des.height['max'].astype(int), 2)
cutdf = pd.cut(df.height, bins=bins, include_lowest=True)
cutdf.value_counts().sort_index().plot.bar()
生成正态分布数据
使用np.random.normal(mean,scale,size)
可以生成很多数值呈正态分布数字。如下图所示,mean就是中间竖线的位置,scale就是横向挤压或拉伸程度,size是生成数字个数。
但是这里也有问题,由于是基于概率的,就无法避免生成及少量超级小或超级大的值,比如身高1厘米或体重300公斤的异常值数据都有可能产生。最简单的情况是对生成后的数据用DataFrame.loc()
条件表达式直接截取最小值和最大值之间的值。
下面是代码部分。首先使用一个男生名字列表来生成一系列name字段,这个数据可以从下面的百度网盘下载(请参见留言区)。
girlnamedf=pd.read_csv('datasets/En_girl_names.csv',index_col=0)
girldf.head()
下面是生成数据的代码,先生成正态分布的身高,然后生成正态分布的bmi体重指数,然后根据身高和体重指数计算出体重,根据bmi进行分箱操作生成fitness健康标签。最后使用loc把异常值去除。
girldf2 = pd.DataFrame(girlnamedf.sample(frac=1)[:ncount]['0'].to_list(),columns=['name'])
girldf2['height'] = np.random.normal(170, 5, ncount).astype(int) #正态分布身高
girldf2['bmi'] = np.random.normal(20, 5, ncount).round(1) #正态分布bmi
girldf2['weight'] = [int(h * h * b / 10000) for h, b in zip(girldf2.height, girldf2.bmi)]
bins = [0, 18, 25, 100]
labels = ['slim', 'healthy', 'fat']
girldf2['fitness'] = pd.cut(girldf2['bmi'], bins=bins, labels=labels)
girldf2['sex'] = 'woman'
girldf2 = girldf2.loc[(girldf2.height > 150) & (girldf2.height < 210), :]
girldf2 = girldf2.loc[(girldf2.bmi > 15) & (girldf2.bmi < 30), :]
girldf2=girldf2[:100]
girldf2.head(5)
合并数据表
同理也可以生成女生数据girldf2。男女生数据合并使用concat方法,代码如下:
boygirldf=pd.concat([boydf2,girldf2])
boygirldf=pd.DataFrame(boygirldf.sample(frac=1))
boygirldf
最后保存为csv文件。
boygirldf.to_csv('datasets/boygirl200.csv')
最终可以使用开篇的代码进行测试,也可以随时使用boygirldf.fitness.value_counts()
查看实际数据分布情况。
每个人的智能新时代
如果您发现文章错误,请不吝留言指正;
如果您觉得有用,请点喜欢;
如果您觉得很有用,欢迎转载~
END
网友评论