【第二节】python数据分析入门 数据处理、基础可视化与多样性分析

导入数据

继续上一节,python3.7, maxOS + jupyter notebook 参考的是*《利用Python进行数据分析》*一书,这次使用的是1880-2010年间全美婴儿姓名,下载估计需要翻🧱但我还是提供网址https://www.ssa.gov/oact/babynames/limits.html
然后选择“National data”(如果不能下载可以私戳我)解压后是很多很多的txt文档,相比前一个movie的数据集,这个数据集体量更大并且具有明确的时间区分。
在这里插入图片描述
由于这是一个非常标准的以逗号隔开的格式,所以使用pandas.read_csv将其加载到DataFrame中:

import pandas as pd
names1880 = pd.read_csv('/Users/wangchenghang/Desktop/names/yob1880.txt',names=['name', 'sex', 'births'])

这些文件中仅含当年出现超过5次的名字。为了简单起见,我们可以用births列的sex分组表示该年度的births总计:

names1880.groupby('sex').births.sum()

结果如下:

数据聚合+分析前准备

由于该数据集按年度被分隔成了多个文件,所以第一件事就是要将所有数据都组装到一个DataFrame里面,并加上一个year的字段。 使用pandas.concat即可达到这个目的:

#2019是目前最后一个有效年份
years = range(1880,2019)
pieces = []
columns = ['name', 'sex', 'births']

for year in years:
    path = '/Users/vicky/Desktop/names/yob%d.txt' %year
    frame = pd.read_csv(path, names = columns)
    
    frame['year'] = year
    pieces.append(frame)
    
#将数据整合到单个dataframe中   
names = pd.concat(pieces, ignore_index= True)

这里需要注意:

  • concat默认是按行将多个Dataframe组合到一起的
  • igonre_index=True,是因为我们不希望保留read_csv所返回的原始行号

现在得到的巨大的Dataframe如下图所示:

有了这些数据后,我们就可以使用groupbypivot_table在year和sex级别上对其进行聚合了:

total_births = names.pivot_table('births', index='year', columns='sex', aggfunc=sum)

顺便可视化一下:

total_births.plot(title='Total births by sex and year')

在这里插入图片描述
下面可以继续插入一个prop列,用于存放指定名字的婴儿数相对总出生数的比例。prop值为0.02表示100名婴儿中有2名取了当前的名字。因此,我们先按year和sex分组,然后再将新列加到各个分组上:

def add_prop(group):
    births = group.births.astype(float)
    
    group['prop'] = births / births.sum()
    return group
names = names.groupby(['year','sex']).apply(add_prop)

记得之前想了好久怎么做也没做出来,反正这一步是真的学到了👌👌👌,得到的表应为:

为了保险我们再来检验一下所有的prop加和是不是为1,由于是float型,这里使用的是np.allclose
在这里插入图片描述
看起来没有错误👍 但为了实现更进一步的分析, 还需要取出该数据的一个子集:每对sex/year组合的前1000个名字。这又是一个分组操作:

def get_top1000(group):
    return group.sort_values(by='births',ascending=False)[:1000]
    
grouped = names.groupby(['year','sex'])
top1000 = grouped.apply(get_top1000)

得到如下Dataframe

分析趋势

有了完整的数据集和刚才生成的top1000数据集,我们可以开始分析各种命名趋势了。首先将前1000个名字分为男女两个部分:

boys = top1000[top1000.sex == 'M']
girls = top1000[top1000.sex == 'F']

我们先生成一张按year和name统计的总出生透视表:

top1000.index = top1000.index.droplevel()
total_births = top1000.pivot_table('births', index = 'year', columns='name' , aggfunc=sum)
total_births

得到:
在这里插入图片描述
我们再用plot方法绘制几个名字的曲线:

subset = total_births[['John','Harry','Mary','Marilyn']]
subset.plot(subplots=True, figsize=(12,10),grid=False,title='Number of births per year')

在这里插入图片描述

评估多样性

这个其实牵扯一个思路问题,虽然书上写的思路很直接,但其实如果直观的去解决这个问题还是有些麻烦的。 基于之前top1000的表,那如果最流行的1000个名字所占的比例减少,那么也可以侧面证明:

top1000.index = top1000.index.droplevel()
table = top1000.pivot_table('prop',index='year',columns='sex' , aggfunc=sum)
table.plot(title = 'Sum of table1000.prop by year and sex', yticks = np.linspace(0, 1.2, 13), xticks = range(1880,2030,20)

得到的图为:
在这里插入图片描述
确实前1000个流行的名字所占比例在下降。 但考虑另一个方法是计算占出生人数前50%的不同名字的数量(因为计算比较复杂,这里取1990年和2018年做比较):
在这里插入图片描述
在这里插入图片描述
可以明显的看出,名字的数量增长了许多。既然这个方法看起来是可行的,我们就可以对所有year/sex组合执行这个计算。按这两个字段进行groupby处理,然后用一个函数计算各分组的这个值:

def get_quantile_count(group, q=0.5):
    gruop = group.sort_values(by='prop' ,ascending= False)
    return group.prop.cumsum().searchsorted(q)+1

diversity = top1000.groupby(['year','sex']).apply(get_quantile_count)
diversity = diversity.unstack('sex')
diversity.plot(title = 'Number of popular names in top 50%', yticks = np.linspace(0, 300, 13), xticks = range(1880,2030,20))

结果如下:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值